ExpressでCSVをダウンロードさせてExcelで開かせようということになりました。
まずUTF-8な環境のNode.jsなのでUTF-8でどうにかできないかと思っていると、以下の記事でUTF-16LEのTSVのファイルの拡張子がcsvならエクセルで開けるとの情報を得ました。
Win/Mac どちらの Excel でも正しく開ける Unicode な csv の出力方法
UTF-16ならBufferで扱えるし、Shift-JISよりはいいじゃないかと思ったら、古いExcelでは文字化けしてしまいました。
苦悩の末Shift-JISのCSVを出力するかと思い、次の記事を参考にiconvで変換しようと試みました。
Node.js (Express) で伝統的な CSV を出力する
何か文字化けしてダメだったので、今回は上2つでダメな場合どうしたかというのをメモ書きして置こうと思います。
文字コード変換
node-iconvがなぜか文字を正常に変換してくれなかったので、Shift-JISに特化したモジュールを使うことにします。
インストールなどもこちらに従ってください。
Expressの記述
Expressでsend等でデータを返すとContent-Typeのcharsetがutf-8に必ず書き換わっているようなので、上の記事と同じくwrite等を使います。
jconvと組み合わせて次のようにしました。
また今回はExcelで開くことを考慮し、Excelで中のデータが必ず文字列として表示できるよう、="データ"
という感じでデータをまとめます(普通のCSVにしたい場合は=を削ってください)。
const jconv = require( 'jconv' );
... 省略 ...
router.get('/path/to/download/csv', (req,res,next) => {
const filename = '日本語を含むファイル名';
// 日本語UTF-8のファイル名をダウンロードするファイル名として使う。
res.setHeader( 'Content-disposition', 'attachment; filename*=UTF-8\'\'' + encodeURIComponent( filename + '.csv' ) );
// Content-Typeをcsvにして文字コードもShift-JISにする。
res.setHeader( 'Content-Type', 'text/csv; charset=Shift_JIS' );
const data = [
[ 'CSV', 'の', 'データ' ],
[ 'まぁ', 'こんな', '感じで' ],
];
const str = data.map( ( v ) => {
// 普通のCSVにしたい場合は、ここの2個所の=を削る
return '="' v.join( '",="' ) + '"';
} ).join( "\r\n" );
res.write( jconv.convert( str, 'UTF8', 'SJIS' ) );
res.end();
});
これでめでたくShift-JISのCSVを入手できましたとさ。
終わりに
- ふぁっきゅーExcel
- Win/Macでのファイル読み込みくらい同じ挙動にしてくれ……orz
- 後UTF-8とかでも読み込んでorz