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

NestJS中如何在WebSocket场景下使用FileInterceptor?

WebSocket场景下文件上传实现说明

NestJS内置的FileInterceptor是基于multer封装的HTTP场景专用拦截器,依赖HTTP请求的multipart/form-data流解析逻辑,无法直接在WebSocket网关中生效——WebSocket传输的是独立的文本/二进制帧,没有内置的multipart格式解析能力,直接挂载你写的那段拦截器代码不会触发文件解析逻辑。

可直接复用原有配置的实现方案

你原配置里的上传目录、文件大小限制规则可以完全平移,根据文件大小选对应实现即可:

方案1:小文件(如头像)Base64传输(实现成本最低)

  • 客户端处理:选中文件后读取为Base64字符串,和其他业务参数一起封装成普通WebSocket消息发送,消息结构参考:
    {
      "event": "uploadProfilePhoto",
      "data": {
        "fileName": "avatar.jpg",
        "fileBase64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
      }
    }
    
  • 服务端处理:在WebSocket消息订阅方法里手动完成校验、存盘逻辑,完全对齐你原来的拦截器配置:
    import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
    import * as fs from 'fs';
    import * as path from 'path';
    
    // 平移你原拦截器的配置
    const UPLOAD_DEST = '../uploads/profilePictures';
    const MAX_FILE_SIZE = 10 * byte; // 和你原limits.fileSize配置保持一致
    
    @WebSocketGateway({ cors: true })
    export class FileUploadGateway {
      @SubscribeMessage('uploadProfilePhoto')
      async handleAvatarUpload(@MessageBody() payload: { fileName: string, fileBase64: string }) {
        // 剥离Base64文件头转Buffer
        const pureBase64 = payload.fileBase64.replace(/^data:image\/\w+;base64,/, '');
        const fileBuffer = Buffer.from(pureBase64, 'base64');
    
        // 对齐原拦截器的大小校验逻辑
        if (fileBuffer.length > MAX_FILE_SIZE) {
          return { success: false, message: '文件大小超出限制' };
        }
    
        // 目录不存在则递归创建
        if (!fs.existsSync(UPLOAD_DEST)) {
          fs.mkdirSync(UPLOAD_DEST, { recursive: true });
        }
    
        // 生成唯一文件名写入目标路径
        const saveFileName = `${Date.now()}-${path.basename(payload.fileName)}`;
        const fullSavePath = path.join(UPLOAD_DEST, saveFileName);
        fs.writeFileSync(fullSavePath, fileBuffer);
    
        return { success: true, message: '上传成功', filePath: fullSavePath };
      }
    }
    

方案2:大文件分片传输(适合大于1MB的文件)

如果要传更大的文件,单帧传Base64会有性能问题,用分片逻辑实现:

  • 客户端把文件按100KB~1MB的大小切成分片,逐片发送,消息里携带文件唯一标识、当前分片序号、总分片数、分片二进制内容
  • 服务端用内存或者临时文件缓存每个上传任务的分片,收齐所有分片后按序号合并成完整文件,同样做大小校验后存入你配置的../uploads/profilePictures目录即可,过程中还可以实时给客户端回传上传进度。

注意:不要尝试直接给WebSocket订阅方法添加@UseInterceptors(FileInterceptor(...))装饰器。FileInterceptor内部依赖HTTP上下文的request对象获取multipart流,WebSocket上下文不存在该对象,运行时会直接抛出空对象错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:39:14