如何用Node.js Express保存Xero返回的原始文件内容
我正在集成Xero的软件中下载文件,已经获取到Xero的响应,但不知道如何保存返回的原始文件内容。参考了Xero的附件API文档后,得到的响应是乱码格式的原始内容:
\����[�����\u0012���\u0010����������="�\u001bֱ�\u0002��Kl�b��6\u0011�,�-��d\u0001�k��V�x�K�+\u0001q(\u0001\u0007NO'�]\u0018���\u0004)\u000e�\b#Ӓ��"��\u000f\u001b�=�u��\f�~%�o�K_�Me\u0005�r�F���"\u0012@�\u0003�k����\u0014\u001d�K�\u001bNK�\u0012\u0006�p0�\u001c\u0012{�\u0000���\u0012k��\u0006�\u0000)7\u0010�p1���yݗƯ�zo>\u0019i�<ҥ�/ښ�K\u0007�T��\u0010�4i��bzaI玼W�_X��n���(P�[\u0003�x�e\u0006�,�-�[H�v���3�<\u0006��O�eG/��ƣnǖ��=3ڼ��O�M�\u0007�>�k�߈�,����\u001bL֩\u001c�\u0012��\u0004�\u0002I��[\u0004�q���S�����.�U�-����.�j��w\u001a����\u0011��U{)Z�\u0003ׯa����+�u\u0003 �a�f�6��K�\u0007�\u0018\u0001\u0001<��\u000ekQ�6�_g��[\u0004���+俋�������}\u000b]����\u0012{]"?���8m��b\u0004wjaM�D���{9����o\u0000\f��=�����\u0000\u0005��ëo��[�\n�~�?\u0013��:j�|��%��$�əT1ʌ\u001c�{�տ\u0001i��_�m��i��Xio4�V���#mt����#\u0013�\u0001�,��q�dW��U=\u0016{?��J����&�l��6G#\u0002O�\u0004\u000fz��Ӕj% >I�\u0000�M���\u0011<l.e+��&+x����6��\t��Ƿ�u\u0012Rl�8*N\u0006}?¿\u0007��>7�_ÿ\u0010x��<ա�4m\u001fN�$����\u0012\u000f�܃¨$⾯��\u0000��|\u0012�Ԧ�/\fkw��/\u0012��r���� l�V��<�;�\u000b�?S�\u0015�ߖ�k�X\u0013Џ�s.�ѼC��\u0011'�mD�]�\u0013-�2(xf��\u0016�2�����s�\u0006�9|*���6���}P��[����d�ݾ�\u001c���\u0016\u0005��C�\u000e��tR�|0���C�\u0002\u0010s��>+�\u0011q�Lg�!�&�\u000f�Q�=0�C�\u0000\t\r�A�\u0004Y������p���H2�\u0019�6\u001c�\u000f�\u0000U.߲\u001a��F�;��\u0002\u000b�b�H�:\u0018������w��|9�O➩���\u001f\u000eu��R4�C\u0004\u0011]G�χ{\u001dѰ�\u000e}�\rw�(�s�@�m\u0002[çG)\fڀ\t��]ߨ��+m�4���Hw\u001ff��5�����)�\u001a��Þ\u0012��V�����m\u0003)�s\u001b�|��a�#���x\u0015���3����jm\u0017èI"N��c[@�\u0018�#�>\u0013'\u0019 \f�5���M&�\u0003�$���>j\u0006\
我尝试了以下代码,但没能成功保存文件:
const response: any = await xeroService.downloadFileFromUrl(attachmentUrls, resAttachment?.xeroTokenInfo); const writer = fs.createWriteStream('image.png'); response?.data?.pipe(writer); res.send(response.data);
核心问题分析
Xero返回的是二进制文件内容,乱码是直接将二进制数据以字符串形式展示导致的。你的代码存在两个关键问题:
- 未确保请求获取的是二进制数据流
- 缺少流操作的错误处理和完成回调
修正后的代码实现
1. 确保请求返回二进制数据
如果使用Axios发起请求,需在配置中指定responseType: 'stream'或responseType: 'arraybuffer',示例:
// xeroService.downloadFileFromUrl 内部的请求配置 const config = { method: 'GET', url: attachmentUrl, headers: { 'Authorization': `Bearer ${token}` }, responseType: 'stream' // 关键:获取流形式的二进制数据 };
2. 正确保存流到文件
添加错误监听和完成回调,确保文件写入成功:
const response: any = await xeroService.downloadFileFromUrl(attachmentUrls, resAttachment?.xeroTokenInfo); const writer = fs.createWriteStream('image.png'); // 处理流的错误和完成事件 response.data.pipe(writer); writer.on('finish', () => { console.log('文件保存成功'); res.send('文件已保存'); }); writer.on('error', (err) => { console.error('文件保存失败:', err); res.status(500).send('文件保存失败'); });
3. ArrayBuffer格式的替代方案
如果获取的是ArrayBuffer类型数据,可直接转为Buffer写入文件:
const buffer = Buffer.from(response.data); fs.writeFile('image.png', buffer, (err) => { if (err) { console.error(err); res.status(500).send('保存失败'); } else { console.log('文件保存成功'); res.send('文件已保存'); } });
额外注意事项
- 不要硬编码文件名
image.png,可从响应头的Content-Type或Xero返回的附件元数据中获取正确的文件名和扩展名 - 确保文件写入路径有足够的读写权限
内容的提问来源于stack exchange,提问作者Harpreet Singh

