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

NestJS使用StreamableFile返回图片流无法正常显示问题

NestJS使用StreamableFile返回图片无法显示的问题

我按照NestJS官网示例用StreamableFile返回图片文件流,但图片无法正常显示,已确认文件存在且路径正确。

原始代码

@Get('/avatar/:userId')
async showAvatar(
    @Param('userId') userId: number, 
    @Res({ passthrough: true }) res: Response
): Promise<StreamableFile> {
    const { filename, mimetype } = await this.fileService.queryAvatar(userId);
    const filePath = join(process.cwd(), `${AVATAR_PATH}/${filename}`);
    const file = createReadStream(filePath); 
    const fileStats = await promises.stat(filePath);
    console.log(fileStats.size) // 50365
    res.set({
        'Content-Type': mimetype,  //  'image/jpeg'
        'Content-Length': fileStats.size,  // 实际响应头中显示396
        'Content-Disposition': 'inline;',
    });
    return new StreamableFile(file);
}

异常现象

  • 控制台打印的文件实际大小是50365,但响应头里的Content-Length却只有396,导致图片数据截断无法显示
  • 改用file.pipe(res)时图片显示正常,此时响应头的Content-Type是image/jpeg;但用StreamableFile时变成了image/jpeg; charset=utf-8

解决方案

  1. 删除手动设置的Content-Length
    StreamableFile会自动处理文件流的长度计算,手动设置的数值会和实际流长度冲突,直接移除res.set中的'Content-Length'配置。

  2. 通过StreamableFile的options设置响应头
    不要用res.set手动设置Content-Type和Content-Disposition,而是在创建StreamableFile时传入options参数,这样可以避免自动添加多余的charset=utf-8:

return new StreamableFile(file, {
  type: mimetype,
  disposition: 'inline'
});
  1. 优化后的完整代码
import { createReadStream } from 'fs';
import { join } from 'path';
import { Get, Param, Res, StreamableFile } from '@nestjs/common';
import { Response } from 'express';

@Get('/avatar/:userId')
async showAvatar(
    @Param('userId') userId: number, 
    @Res({ passthrough: true }) res: Response
): Promise<StreamableFile> {
    const { filename, mimetype } = await this.fileService.queryAvatar(userId);
    const filePath = join(process.cwd(), `${AVATAR_PATH}/${filename}`);
    const file = createReadStream(filePath); 

    return new StreamableFile(file, {
        type: mimetype,
        disposition: 'inline'
    });
}

原因解析

  • StreamableFile内部会自动处理文件流的传输逻辑,手动设置Content-Length会覆盖正确的长度值,导致浏览器接收到不完整的二进制数据
  • 用res.set设置Content-Type时,NestJS的默认响应处理会自动追加charset=utf-8,而图片属于二进制文件,不需要字符编码,这会干扰浏览器的解析逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:22:16