Node.js运行时Azure Function App如何访问multipart/form-data请求文件数据
Azure Function Node.js HTTP触发器直接读取multipart/form-data文件方案
问题根因
- 观察到的
req.body、req.rawBody仅能返回文件名、拿不到实际文件内容,是Azure Function Node.js运行时的默认请求解析逻辑导致的:- 当检测到请求
Content-Type为multipart/form-data时,运行时不会对原始请求流做全量缓存,因此rawBody属性不会存储完整的原始请求报文 - 旧教程提到的
rawBody缓存全量数据的特性,仅对application/json、application/x-www-form-urlencoded等常规请求类型生效,multipart类型的请求流会被运行时直接跳过缓存流程
- 当检测到请求
实现方案(无需前端转base64嵌JSON)
前置依赖
在函数项目根目录安装专门处理multipart表单的解析库,执行命令:npm install formidable
核心配置与代码
Azure Function的req对象是对原生Node.js http.IncomingMessage的封装,可直接获取原始请求可读流完成文件解析,关键是要先关闭运行时的自动请求体解析,避免请求流被提前消费:
- 触发器配置阶段关闭默认body解析:设置
bodyParser.enabled = false这是整个方案能正常读取文件的核心配置,不能省略 - 从封装的request对象上提取原始Node.js请求流,用formidable完成流式解析
以下是V4版本编程模型的可直接运行的示例代码:
const { app } = require('@azure/functions'); const formidable = require('formidable'); const os = require('os'); app.http('HttpTrigger1', { methods: ['POST'], authLevel: 'anonymous', // 关键:关闭运行时自动请求体解析 bodyParser: { enabled: false }, handler: async (request, context) => { // 提取原始Node.js请求可读流 const rawNodeReq = request._req; const formParser = formidable({ uploadDir: os.tmpdir(), // 可自定义为内存流处理,无需落地临时文件 keepExtensions: true }); // 解析multipart请求内容 const { fields, files } = await new Promise((resolve, reject) => { formParser.parse(rawNodeReq, (err, parsedFields, parsedFiles) => { if (err) reject(err); resolve({ fields: parsedFields, files: parsedFiles }); }); }); // 表单中name为file-one的文件,可直接从files对象中获取完整元数据与内容 const uploadedFile = files['file-one']; context.log('成功读取上传文件,原始文件名:', uploadedFile.originalFilename); return { body: JSON.stringify({ status: 'success', message: `文件${uploadedFile.originalFilename}接收完成` }) }; } });
避坑提示
- 务必配置
bodyParser.enabled: false,否则运行时会提前消费请求流,导致handler内读取请求时出现流已结束、无有效数据的问题 - 如果使用V3版本编程模型,核心逻辑完全一致,仅函数注册语法有差异,同样需要关闭默认body解析,从
context.req提取原始请求流即可完成解析 - 该方案支持流式读取大文件,不会将全量文件加载到内存,生产环境可根据需求自定义配置,无需额外在前端做base64编码转换
内容的提问来源于stack exchange,提问作者konkrer
相关产品推荐
相关产品推荐

