https://github.com/ryu1kn/csv-writer
- node 環境で csv write したいときのやつ
- nextjs (express) の response と組み合わせて streaming 返却で利用した
import type { NextApiRequest, NextApiResponse } from 'next'
import { prisma } from 'libs/prisma'
import { createObjectCsvStringifier } from 'csv-writer'
export default async function Csv (
req: NextApiRequest,
res: NextApiResponse,
) {
try {
const filename = 'FILENAME'
const csvStringifier = createObjectCsvStringifier({
header: [
{ title: 'ID', id: 'id' },
{ title: '名前', id: 'name' },
]
})
res.setHeader('Content-Type', 'text/csv')
res.setHeader('Content-Disposition', `attachment; filename="${encodeURI(filename)}.csv"`)
res.write(new Uint8Array([0xEF, 0xBB, 0xBF])) // UTF8 BOM for Windows
res.write(csvStringifier.getHeaderString())
let more = true
let skip = 0
const take = 1000
while (more) {
const records = await prisma.user.findMany({
take,
skip,
where: { /* */ },
orderBy: [{ /* */ }],
})
if (records.length === 0) {
more = false
break
}
// streaming
res.write(csvStringifier.stringifyRecords(records.map(user => ({
id: user.id,
name: user.name,
}))))
skip += take
}
return res.end()
} catch (e: any) {
return res.status(500).send(e?.message)
}
}
import { useMutation } from '@tanstack/react-query'
export const useDownload = () => {
return useMutation({
mutationKey: ['download'],
mutationFn: async ({ start, end }: {
start: string
end: string
}) => {
const res = await fetch('/api/csv', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' }
body: JSON.stringify({ start, end }),
})
if (!res.ok) {
throw new Error(await res.text() || res.statusText)
}
const disposition = res.headers.get('Content-Disposition')
let filename = 'data.csv' // default
if (disposition && disposition.indexOf('attachment') !== -1) {
const filenameRegex = /filename="(.+)"/
const matches = filenameRegex.exec(disposition)
if (matches && matches[1]) {
filename = matches[1]
}
}
const blob = await res.blob()
const url = window.URL.createObjectURL(blob)
const dynamicA = document.createElement('a')
dynamicA.href = url
dynamicA.download = decodeURI(filename)
dynamicA.click()
dynamicA.remove()
window.URL.revokeObjectURL(url)
return url
},
})
}