从Amazon S3下载文档上传为Xero发票附件触发TypeError错误求助
问题根源
你调用Xero接口时传入的body参数类型不符合要求:
- 你通过S3
getObject加.promise()获取到的file.Body是Buffer类型 - Xero的
createInvoiceAttachmentByFileName接口要求body参数为**可读流(Readable Stream)**类型,SDK内部会调用流的.on()方法监听数据事件,Buffer对象不存在该方法,因此抛出TypeError: body.on is not a function错误。
解决方案
有两种可行的修改方式,任选其一即可:
方案1:将获取到的Buffer转为可读流(修改量最小)
在调用Xero上传接口前,把S3返回的Buffer转为可读流即可,Node.js 12及以上版本可直接用内置stream模块的Readable.from方法实现:
首先引入依赖:
const { Readable } = require('stream');
修改主流程中调用sendAttachmentToInvoice的传参:
await xeroService.sendAttachmentToInvoice( integration.tenant.id, sendInvoicesResponse.body.invoices[0].invoiceID, document.name, // 把Buffer转为可读流传入 Readable.from(downloadedDocument.data), downloadedDocument.mimetype, );
方案2:直接从S3获取可读流(性能更优,适合大文件)
无需把整个文件加载到内存转为Buffer,直接返回S3的可读流给Xero接口,修改AWS的downloadDocument方法:
module.exports.downloadDocument = async (key) => { try { const getParams = { Bucket: config.aws.documentsBucket, Key: key, }; // 先获取文件元信息拿到mimetype,再创建可读流 const headData = await s3.headObject(getParams).promise(); const fileStream = s3.getObject(getParams).createReadStream(); return { data: fileStream, mimetype: headData.ContentType, }; } catch (error) { const message = error.message; logger.error(`download document from AWS fail | message=${message}`); throw new Error(message); } };
这种方式避免了大文件场景下的内存占用过高问题,更推荐使用。
额外修复点
你原代码的所有catch分支中存在变量未定义的问题:message没有声明就直接使用,需要补上const message = error.message;,否则会抛出额外的引用错误。
内容的提问来源于stack exchange,提问作者siri
相关产品推荐
相关产品推荐

