【初心者】CSV出力
Q&A
Closed
解決したいこと
現在CSV出力機能を作成しています。
バックエンドで作成されたCSVをフロントエンドでAPIが呼ばれたときに出力させたいです。
しかし、その出力ができておりません。
バックエンド側の処理は変えずに済む解決方法を教えてください。
(補足)
バックエンド側でAPIたたくだけでブラウザにダウンロードされるようにしたいです。
使用技術 vue.js,TypeScript
バックエンド(サービスクラス)
・ここでCSVを作ってBase64エンコードにしてしているようです。
const csvFileValue = {migration}
const csvFolderName: string = 'migration' '_' + generateUUID();
const csvFileName: string = 'migration'+ '_' + getCurrentTime() + '.csv';
// NOTE: csvFileValueは必ず1件のデータを持つため、配列に変換して渡す
await createCsvbyObject(csvFolderName, csvFileName, csvFileHeader, [csvFileValue]);
const binaryData = fs.readFileSync(path.join('/tmp', csvFolderName, csvFileName));
const base64Data = Buffer.from(binaryData).toString('base64');
return { csvFileName, base64Data };
};
// 疑似uuid生成
// TODO:npm install uuid
function generateUUID(): string {
const timestamp = Date.now().toString(16);
const randomHex = Math.floor(Math.random() * 0xffffff).toString(16);
return `${timestamp}-${randomHex}`;
}
//現在時刻取得(yyyymmddhhmmss)
function getCurrentTime() {
const now = new Date();
const res =
'' +
now.getFullYear() +
padZero(now.getMonth() + 1) +
padZero(now.getDate()) +
padZero(now.getHours()) +
padZero(now.getMinutes()) +
padZero(now.getSeconds());
return res;
}
//先頭ゼロ付加
function padZero(num: number) {
return (num < 10 ? '0' : '') + num;
}
バックエンド(関数クラス) サービスの関数をここで呼んでいます
const baseHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const requestId = Number(event.pathParameters?.requestId);
if (!event.pathParameters?.requestId) {
return createResponse(JSON.stringify({ error: 'Invalid or missing requestId' }));
}
const result = await getMigration(requestId);
return createResponse(JSON.stringify(result));
} catch (error) {
if (error instanceof Error) {
return createResponse(JSON.stringify({ error: error.message }));
}
return createResponse(JSON.stringify({ error: '予期せぬエラーが発生しました。' }));
}
};
export const lambdaHandler = middy(baseHandler).use(httpErrorHandlerMiddleware());
フロントエンド(APIを呼びだし)レスポンスの中にはcsvFIleNameは見当たらず...
/**
* postMigrationItem
* @description csvをダウンロード
* @param requestId
* @returns { Promise<void>}
*/
const postMigrationItem = async (requestId: number | null): Promise<void> => {
try {
const response = await apiClient.post(`/migration/file/${requestId}`)
console.log('response:', response)
return response.data
} catch (error: unknown) {
throw new Error('postMigrationItemでエラーが発生しました。')
}
}
フロントエンド(CSVを出力ビジネスロジッククラス) できればバックエンドで作成したCSVをそのまま出力したいですが...
/**
* handleExportButtonClick
* @description CSV出力ボタン押下
*/
const handleExportButtonClick = async (): Promise<void> => {
const migrationFile = await postMigrationItem(requestId.value)
console.log('migrationFile:', migrationFile)
// Base64データをデコード
const binaryString = atob(migrationFile.base64Data)
const binaryLen = binaryString.length
const bytes = new Uint8Array(binaryLen)
for (let i = 0; i < binaryLen; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
// Blobオブジェクトを作成
const blob = new Blob([bytes], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.setAttribute('href', url)
link.setAttribute('download', migrationFile.csvFileName)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
closeModal()
}
0