はじめに
バックエンドにLambdaを使用しているのですが、Excelファイルをそのまま返却しようとすると文字化けしてしまうエラーが発生しましたので、解消方法を記載しておきます。
対象者
この記事は下記のような人を対象にしています。
- PythonのopenpyxlでExcelファイルを作成している
- Lambdaを使用している
結論
Base64エンコードを使用します。
【サーバー側】
excel.py
import openpyxl
import base64
import tempfile
import json
def export_excel():
wb = openpyxl.Workbook()
# ここでシートにデータを書き込む
with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as tmpfile:
wb.save(tmpfile.name)
with open(tmpfile.name, "rb") as excel_file:
# Lambdaの場合エンコード処理が必要
encoded_content = base64.b64encode(excel_file.read()).decode()
response = {
"headers": {
"Content-Type": "application/json",
},
"body": json.dumps(
{
"data": encoded_content,
"headers": {
"Content-Disposition": "attachment; filename=filename.xlsx"
},
}
),
}
return response
【フロントエンド側】
exportExcel.ts
import axios from 'axios'
const exportExcel = async () => {
try {
const response = await axios.get(`https://sample.com/excel`)
const responseBody = JSON.parse(response.data.body)
const encodedContent = responseBody.data
const blob = b64toBlob(
encodedContent,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
)
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.setAttribute('download', 'filename.xlsx')
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
} catch (error) {
throw new Error(`${error as string}`)
}
}
function b64toBlob(b64Data: string, contentType: string): Blob {
const byteCharacters = atob(b64Data)
const byteArrays = []
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
const slice = byteCharacters.slice(offset, offset + 512)
const byteNumbers = new Array(slice.length)
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i)
}
const byteArray = new Uint8Array(byteNumbers)
byteArrays.push(byteArray)
}
return new Blob(byteArrays, { type: contentType })
}
おわりに
LambdaでExcelファイルをエクスポートすると文字化けしてしまうエラーの解消方法についてまとめました。