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

纯Node.js环境下从Buffer提取多类型文件至变量的方法咨询

纯Node.js解析多文件上传的Buffer(无框架/第三方包)

要提取多文件的Buffer,核心是手动解析multipart/form-data格式的请求体——这是客户端上传多文件时默认使用的格式,你拿到的Buffer里包含了分隔符、文件头信息和文件内容的混合数据,必须拆分后才能拿到单个文件的内容。

实现步骤

  1. 获取分隔符(Boundary):从请求的Content-Type头中提取分隔符,它是区分不同文件块的标记。
  2. 拆分请求体:用分隔符把整个Buffer分割成多个部分,每个部分对应一个文件。
  3. 解析每个文件块:从每个部分中拆分出头信息(文件名、Content-Type)和文件内容Buffer。

完整代码示例

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
  // 只处理POST类型的multipart请求
  if (req.method === 'POST' && req.headers['content-type']?.startsWith('multipart/form-data')) {
    const bodyChunks = [];

    req.on('data', (chunk) => {
      bodyChunks.push(chunk);
    });

    req.on('end', () => {
      const fullBody = Buffer.concat(bodyChunks);
      // 1. 提取分隔符
      const contentType = req.headers['content-type'];
      const boundaryStr = contentType.split('boundary=')[1];
      if (!boundaryStr) {
        res.writeHead(400);
        res.end('无效的多文件请求');
        return;
      }
      const boundary = Buffer.from(`--${boundaryStr}`);

      // 2. 拆分请求体为各个文件块,过滤掉空块和结尾标记
      const fileParts = fullBody.split(boundary).filter(part => {
        return part.length > 0 && !part.toString().includes('--');
      });

      // 3. 解析每个文件块,提取文件信息和内容
      const extractedFiles = [];
      for (const part of fileParts) {
        // 找到头信息和内容的分隔点(\r\n\r\n是标准分隔符)
        const headerEndIndex = part.indexOf(Buffer.from('\r\n\r\n'));
        if (headerEndIndex === -1) continue;

        // 拆分出头信息和文件内容
        const headerBuffer = part.slice(0, headerEndIndex);
        const fileContentBuffer = part.slice(headerEndIndex + 4); // 跳过\r\n\r\n

        // 解析头信息(转成UTF-8字符串)
        const headerStr = headerBuffer.toString('utf8');
        const filenameMatch = headerStr.match(/filename="([^"]+)"/);
        const contentTypeMatch = headerStr.match(/Content-Type: ([^\r\n]+)/);

        if (filenameMatch) {
          extractedFiles.push({
            filename: filenameMatch[1],
            contentType: contentTypeMatch ? contentTypeMatch[1] : 'application/octet-stream',
            content: fileContentBuffer // 单个文件的Buffer变量
          });
        }
      }

      // 现在extractedFiles数组中就是所有文件的信息,可直接使用或保存
      console.log(`解析到 ${extractedFiles.length} 个文件`);
      extractedFiles.forEach((file, idx) => {
        console.log(`文件 ${idx+1}: ${file.filename},大小 ${file.content.length} 字节`);
        // 示例:保存到磁盘
        fs.writeFileSync(`./${file.filename}`, file.content);
      });

      res.writeHead(200);
      res.end(`成功接收 ${extractedFiles.length} 个文件`);
    });
  } else {
    res.writeHead(404);
    res.end('页面未找到');
  }
});

server.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

注意事项

  • 内存占用问题:上述代码会把整个请求体读入内存,若上传大文件(比如几百MB),可能导致内存溢出。如果需要处理大文件,需要改成流式解析(边读边拆分处理)。
  • 换行符兼容:部分客户端可能用\n\n作为头信息和内容的分隔符,可根据实际情况调整判断逻辑。
  • 文件名编码:若遇到中文或特殊字符文件名乱码,可能需要额外处理编码转换(比如解析filename*=UTF-8''...格式的头信息)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:47:02