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>