AWS Lambda:创建和下载 EXCEL 文件时出现编码问题

AWS Lambda: encoding problem when creating and downloading EXCEL file

我正在创建一个微服务来动态生成 EXCEL 文件并下载它们。

我有一个 AWS Api 网关和一个 Python 3.8 Lambda 函数。要创建 EXCEL,我使用 Openpyxl 包。

文件生成正常,但当我下载它时,我似乎遇到了一些我无法弄清楚的编码问题。

Lambda

在这里我总结了函数,突出显示了结尾,我将文件保存到缓冲区并 return 它。

wb = I create my Workbook correctly

buffer = io.BytesIO()
wb.save(buffer)
    
excel_final = buffer.getvalue()
buffer.close()
         
response = excel_final

return response

测试 Lambda 输出时,我看到这个响应,看起来是 Unicode:

“PK\u0003\u0004\u0014\u0000\u0000\u0000\b\u0000}t\u008dT\u………….”

Api 网关

集成响应设置为直通,方法响应设置为 application/xml。尝试了不同的设置,但无法正常工作。

我在测试API方法的时候,也得到了如下格式的数据,我觉得是utf-8解码的:

“PK�u�TAMb��docProps/app.xmlM�= 1D��q��A�Bb@�R��{/�dC�B~�9��noF� g*�-�T��"���N]�n�h�cy;�Ό�HI`��� ���M��F�r�xN��pe'å! �rmީ�5�&����;i^PK�u�T�z���docProps/core.xml���N�0�_e�u�V=DY.C�@Bb�[�x[E�F�Q��'-[������V����

Javascript

在我的 request.onload 中,我得到字节响应并将其转换为 Blob 以供下载。

let blob = this.response;
let final_blob = new Blob([blob], {type: 'application/xml'})

文件已下载但被识别为已损坏。打不开

测试

我尝试了不同的内容类型,在 Lambda 中 coding/encoding 或 Javascript,但从未成功。

欢迎提供任何线索!

我终于让它工作了,我可以直接从 Lambda 下载 PDF、EXCEL 或 ZIP 文件,而无需实际将文件存储在 S3 存储桶中。

Lambda

Lambdas 和 Api 网关之间的通信需要 base64 编码,所以在 Lambda 中我只是 return 裸露的 base64 编码二进制文件。

wb = I create my Workbook correctly 
buffer = io.BytesIO() 
wb.save(buffer) 
excel_final = buffer.getvalue() 
buffer.close()

return base64.b64encode(excel_final)

Api 网关 - 设置

首先转到 API 的设置并在 'Binary Media Types' 添加 application/ms-excel

Api 网关 - 方法响应

在“响应 Headers for 200”处添加 Content-Type header。

在“Response Body for 200”处添加 application/ms-excel 响应模型

Api 网关 - 集成响应

Content handling 设置为 Convert to binary (if needed)

在“Header 映射”处将 Content-Type 值设置为 application/ms-excel

前端

现在您将收到一个二进制文件作为您的回复。 只需生成 blob 并根据需要下载即可。

let blob = this.response;
let final_blob = new Blob([blob], {type: 'application/xml'});

// In my case I generate a link and click it

结论

在我的菜鸟中,我一直在摆弄配置链中总是有问题的配置。在我的辩护中,我必须说文档并没有太大帮助。

一旦我让它开始工作,它似乎并没有那么麻烦,而且对任何类型的二进制文件都非常有用。

使用 S3 方法,您需要不必要地存储一个文件,再次请求下载它,最后将其从存储桶中删除。

希望对您有所帮助!