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 csvStringifier = createObjectCsvStringifier({
header: [
{ title: 'ID', id: 'id' },
{ title: '名前', id: 'name' },
]
})
res.setHeader('Content-Type', 'text/csv')
res.setHeader('Content-Disposition', 'attachment; filename="data.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 users = await prisma.user.findMany({ take, skip })
if (users.length === 0) {
more = false
break
}
// streaming
res.write(csvStringifier.stringifyRecords(users.map(user => ({
id: user.id,
name: user.name,
}))))
skip += take
}
res.end()
} catch (e: any) {
return res.status(500).send(e?.message)
}
}
import { useMutation } from '@tanstack/react-query'
export const useDownload = ({ filename, api }: {
filename: string
api: string
}) => {
return useMutation({
mutationKey: ['download'],
mutationFn: async () => {
const response = await fetch(api)
if (!response.ok) {
throw new Error(await response.text() || response.statusText)
}
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const dynamicA = document.createElement('a')
dynamicA.href = url
dynamicA.download = filename
dynamicA.click()
dynamicA.remove()
window.URL.revokeObjectURL(url)
return url
},
})
}