Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active April 16, 2024 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yano3nora/753cb2724c00a9e236a4d7c439673cd2 to your computer and use it in GitHub Desktop.
Save yano3nora/753cb2724c00a9e236a4d7c439673cd2 to your computer and use it in GitHub Desktop.
csv-writer

Overview

https://github.com/ryu1kn/csv-writer

  • node 環境で csv write したいときのやつ
  • nextjs (express) の response と組み合わせて streaming 返却で利用した

Examples

API

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)
  }
}

Front

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
    },
  })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment