使用request js时,为何requ().pipe(res)可行而res.send(result)无法正常工作?
为什么
requ().pipe(res)可行但requ().then(result => res.send(result))不行? 这个问题的核心在于request-promise(rp)默认的响应处理逻辑,以及pipe()和res.send()对数据的处理差异,我来拆解清楚:
1. requ().pipe(res)为什么能正常工作?
当你直接调用pipe()时,rp底层依托request库的流接口运作——它会把API返回的原始二进制数据流直接传输到Express的res响应对象。整个过程没有对数据做任何额外的编码转换,流是逐块传输的,完整保留了文件的原始字节,所以客户端能拿到可正常解析的完整文件。
2. then()里用res.send(result)为什么会失败?
默认情况下,request-promise会把响应体自动转换成字符串(它默认的encoding参数为utf8)。如果你的附件是二进制文件(比如图片、PDF、压缩包等),把二进制字节直接转成UTF-8字符串会导致字节丢失或乱码——因为很多二进制字节并不对应有效的UTF-8字符。
当你把这个损坏的字符串传给res.send()时,Express会把它当成普通文本发送,不仅内容已经损坏,还会设置错误的Content-Type(比如text/html),客户端自然无法识别成正常的文件。
解决办法
要让then()的方式生效,只需要修改rp的请求配置,让它返回原始的二进制Buffer而不是字符串:
function requ(){ const options = { uri: `api/tasks/${id}/attachments/${attachmentId}`, encoding: null // 关键:禁用自动编码,返回原始二进制Buffer } return rp.get(options) } requ().then((result)=>{ // 现在result是Buffer类型,完整保留了文件的原始字节 // 可以根据文件类型手动设置Content-Type,比如PDF: // res.type('application/pdf') res.send(result) })
这样处理后,result是完整的二进制Buffer,res.send()会正确识别数据类型,设置合适的响应头,客户端就能正常接收并解析文件了。
补充:如果你的附件是纯文本文件(比如.txt、.json),默认的字符串转换不会有问题,但二进制文件必须用encoding: null来保证数据完整性。
内容的提问来源于stack exchange,提问作者Alex Carlos
相关产品推荐
相关产品推荐

