CSV一括インポート機能の実装で詰まった点
CSV一括インポート機能の実装で詰まった点
求人AIツールにCSV一括インポート機能を実装した。
求人サイトから数百件の求人原稿をエクスポートして、まとめてインポート→AIで改善→再エクスポート、という運用を想定している。
実装自体はシンプルだったけど、実運用で詰まったポイントがいくつかあった。
詰まったポイント1: 文字コード問題
日本のExcelからエクスポートされたCSVは、Shift_JISであることが多い。
ブラウザのFileReaderはデフォルトでUTF-8として読み込むので、文字化けが発生する。
解決策
const reader = new FileReader();
reader.readAsText(file, 'Shift_JIS'); // エンコーディング指定
でも、ユーザーが「UTF-8か Shift_JIS か」を意識するのは無理。
最終的には自動判定を実装した:
async function detectEncoding(file: File): Promise<string> {
const buffer = await file.arrayBuffer();
const uint8 = new Uint8Array(buffer);
// BOMチェック
if (uint8[0] === 0xEF && uint8[1] === 0xBB && uint8[2] === 0xBF) {
return 'UTF-8';
}
// Shift_JIS判定(簡易版)
// 実際にはライブラリ使う方が確実
return 'Shift_JIS';
}
詰まったポイント2: カラム名のバラつき
求人サイトごとにCSVのカラム名が違う:
– 「仕事内容」「業務内容」「職務内容」
– 「給与」「月給」「賃金」
解決策
カラムマッピング機能を実装。
インポート時に「このカラムは何に対応しますか?」とユーザーに選ばせる。
<select>
<option value="job_description">仕事内容</option>
<option value="salary">給与</option>
<option value="location">勤務地</option>
</select>
よくあるパターンは自動マッピングで埋めて、不明な列だけユーザーに確認させる。
詰まったポイント3: 大量データの処理
1000件のCSVをインポートすると、ブラウザが固まる。
解決策
バッチ処理APIを別途実装し、サーバー側で並列処理する仕組みにした。
// src/app/api/batch-import/route.ts
export async function POST(req: Request) {
const { csvData } = await req.json();
// 100件ずつバッチ処理
for (let i = 0; i < csvData.length; i += 100) {
const batch = csvData.slice(i, i + 100);
await processBatch(batch);
}
}
フロントエンドはプログレスバーを表示するだけ。
まとめ
CSV処理は「動けばいい」と思いがちだが、実運用では細かい問題が山積み。
- 文字コード自動判定
- カラムマッピング
- 大量データ対応
この3つを押さえておけば、ユーザーに優しいCSVインポート機能が作れる。
タグ: #開発実績 #エラー解決 #CSV処理