NestJS + NuxtでひさびさにCSVでかつエクセルでもそのまま開けるようにShift_JIS形式にエンコードする必要があり、ハマったのでメモ。
いろいろ試してbase64形式で返す形に落ち着いた。
NestJSのバージョン
"@nestjs/common": "10.3.8", "@nestjs/config": "3.2.2", "@nestjs/core": "10.3.8",
Nuxtのバージョン
"nuxt": "3.11.2",
NestJS側にはencoding-japanese
をインストールします
以下コードは必要なところだけ抜粋で動作未確認です
NestJSコントローラ
import * as Encoding from 'encoding-japanese' // 略 export class CsvController { @Get() async getJobCsvSjis() { // CSVのutf-8文字列を返す架空メソッド const csv = await getCsvString(id) return this.encodeToSjisBase64(csv) } private encodeToSjisBase64(csv: string) { const unicodeArray = Encoding.stringToCode(csv) const sjisArray = Encoding.convert(unicodeArray, { from: 'UNICODE', to: 'SJIS', }) const base64str = Encoding.base64Encode(sjisArray) return 'data:text/csv;base64,' + base64str } }
Nuxt側ではdowload属性つけたaタグクリック形式。 NestJS側で返したbase64文字列をそのままhrefにぶっこみます。
Nuxt
<template> <button c@click="downloadCsv()">SJIS CSV</button> </template> <script setup> const downloadCsv = async () => { isLoading.value = true const res = await $fetch(`/csv/${job}`, { method: 'GET', }) const link = document.createElement('a') link.href = res link.download = `sjis.csv` link.click() link.remove() } </script>