You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS CORS代理下载图片或文件返回编码数据问题排查请求

问题分析

你遇到的核心问题是axios默认会将响应数据自动解析为文本/JSON,而图片这类二进制文件被转换成UTF-8字符串后,再通过JSON.stringify写入响应,就会破坏原始的二进制结构,导致下载的文件是编码后的乱码内容。

解决方案

要正确代理二进制文件,你需要让axios保留原始的二进制数据,并且直接将其转发到客户端响应中,而不是做字符串化处理。具体修改如下:

1. 修改axios请求配置

添加responseType: 'stream'(或者'arraybuffer'),告诉axios不要自动解析响应数据,保留原始的二进制流:

const response: AxiosResponse = await axios.get(url, {
  timeout: 5000,
  responseType: 'stream' // 关键:保留二进制流
})

2. 直接转发响应流

不需要手动writeHead、write和end,可以直接将axios获取的响应流pipe到客户端响应中,这样能自动处理所有的二进制数据和响应头:

res.set(response.headers);
response.data.pipe(res);

完整修改后的代码

@Controller('cors')
export class CorsController {
  constructor(private readonly corsService: CorsService) { }
  
  @Get()
  async get(@Query('cd') uri: string, @Response() res: ExpressResponse) {
    try {
      let url = uri.charAt(0) == '/' ? uri.substring(1) : uri;
      const response: AxiosResponse = await axios.get(url, { 
        timeout: 5000,
        responseType: 'stream' // 保留二进制流
      })
      // 设置响应头,排除可能导致冲突的头字段
      const allowedHeaders = Object.fromEntries(
        Object.entries(response.headers).filter(([key]) => 
          !['transfer-encoding', 'connection'].includes(key.toLowerCase())
        )
      );
      res.set(allowedHeaders);
      // 直接将响应流转发给客户端
      response.data.pipe(res);
    } catch (error) {
      res.status(error.response?.status || 500).send(error.message);
    }
  }
}

额外说明

  • 使用responseType: 'stream'比'arraybuffer'更高效,尤其是处理大文件时,因为它是流式传输,不需要把整个文件加载到内存中。
  • 过滤掉transfer-encoding和connection这类头,是因为Express会自动处理这些字段,避免手动设置导致的冲突。
  • 错误处理部分改为用res.status(...).send(...),能正确向客户端返回错误状态码和信息,而不是简单返回字符串。

内容的提问来源于stack exchange,提问作者Vansham Aggarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:12:51