纯Node.js环境下从Buffer提取多类型文件至变量的方法咨询
纯Node.js解析多文件上传的Buffer(无框架/第三方包)
要提取多文件的Buffer,核心是手动解析multipart/form-data格式的请求体——这是客户端上传多文件时默认使用的格式,你拿到的Buffer里包含了分隔符、文件头信息和文件内容的混合数据,必须拆分后才能拿到单个文件的内容。
实现步骤
- 获取分隔符(Boundary):从请求的
Content-Type头中提取分隔符,它是区分不同文件块的标记。 - 拆分请求体:用分隔符把整个Buffer分割成多个部分,每个部分对应一个文件。
- 解析每个文件块:从每个部分中拆分出头信息(文件名、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
相关产品推荐
相关产品推荐

