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

在TypeScript Azure Function中处理HTTP Form-Data的方案咨询

解决方案

方案一:使用busboy库(推荐)

busboy支持流式解析Form-Data,适配Azure Functions的HttpRequest对象(v3/v4均兼容),能同时处理文本字段和文件。

步骤:

  1. 安装依赖
npm install busboy @types/busboy
  1. 实现代码
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import Busboy from "busboy";
import { Readable } from "stream";

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
  return new Promise((resolve, reject) => {
    const busboy = new Busboy({ headers: req.headers });
    const parseResult = {
      fields: {} as Record<string, string>,
      files: {} as Record<string, { buffer: Buffer, filename: string }>
    };

    // 处理文本字段
    busboy.on("field", (fieldName, value) => {
      parseResult.fields[fieldName] = value;
    });

    // 处理文件,收集buffer
    busboy.on("file", (fieldName, fileStream, filename) => {
      const chunks: Buffer[] = [];
      fileStream.on("data", (chunk) => chunks.push(chunk));
      fileStream.on("end", () => {
        parseResult.files[fieldName] = {
          buffer: Buffer.concat(chunks),
          filename: filename || "unknown"
        };
      });
    });

    // 解析完成后的逻辑
    busboy.on("finish", () => {
      context.log("解析得到文本字段:", parseResult.fields);
      context.log("解析得到文件数量:", Object.keys(parseResult.files).length);
      
      context.res = {
        status: 200,
        body: {
          message: "Form-Data解析成功",
          fields: parseResult.fields,
          fileInfo: Object.entries(parseResult.files).map(([name, file]) => ({
            fieldName: name,
            filename: file.filename,
            size: file.buffer.length
          }))
        }
      };
      resolve();
    });

    // 处理解析错误
    busboy.on("error", (err) => {
      context.log.error("Form-Data解析失败:", err);
      context.res = {
        status: 500,
        body: { message: "解析请求数据失败" }
      };
      reject(err);
    });

    // 根据Azure Functions版本处理请求体
    if (req.body instanceof Buffer) {
      Readable.from(req.body).pipe(busboy);
    } else if (req.body instanceof ReadableStream) {
      (req.body as unknown as NodeJS.ReadableStream).pipe(busboy);
    } else {
      context.res = { status: 400, body: "不支持的请求体类型" };
      resolve();
    }
  });
};

export default httpTrigger;

方案二:修复parse-multipart库的用法

parse-multipart本身支持解析文本字段,只需手动区分文件和文本类型即可。

步骤:

  1. 确保已安装依赖
npm install parse-multipart
  1. 实现代码
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import * as multipart from "parse-multipart";
import { Readable } from "stream";

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
  // 从请求头获取Form-Data的boundary
  const contentType = req.headers["content-type"] || "";
  const boundary = multipart.getBoundary(contentType);
  if (!boundary) {
    context.res = { status: 400, body: "无效的Form-Data请求,缺少boundary" };
    return;
  }

  // 将请求体转为Buffer(兼容v3/v4)
  let rawBody: Buffer;
  try {
    if (req.body instanceof Buffer) {
      rawBody = req.body;
    } else if (req.body instanceof ReadableStream) {
      rawBody = await new Promise((resolve, reject) => {
        const chunks: Buffer[] = [];
        const stream = req.body as unknown as NodeJS.ReadableStream;
        stream.on("data", (chunk) => chunks.push(chunk));
        stream.on("end", () => resolve(Buffer.concat(chunks)));
        stream.on("error", reject);
      });
    } else {
      context.res = { status: 400, body: "请求体类型不支持" };
      return;
    }
  } catch (err) {
    context.log.error("读取请求体失败:", err);
    context.res = { status: 500, body: "读取请求数据失败" };
    return;
  }

  // 解析所有parts
  const parts = multipart.Parse(rawBody, boundary);
  const fields: Record<string, string> = {};
  const files: Record<string, { buffer: Buffer, filename: string }> = {};

  parts.forEach(part => {
    if (part.filename) {
      files[part.name] = { buffer: part.data, filename: part.filename };
    } else {
      fields[part.name] = part.data.toString("utf8");
    }
  });

  // 使用解析结果
  context.log("文本字段:", fields);
  context.log("文件信息:", files);
  context.res = {
    status: 200,
    body: {
      fields,
      files: Object.entries(files).map(([name, file]) => ({
        fieldName: name,
        filename: file.filename,
        size: file.buffer.length
      }))
    }
  };
};

export default httpTrigger;

注意事项

  • Azure Functions v4的HttpRequest.body是ReadableStream,v3版本则是Buffer,代码中已做兼容处理。
  • 处理大文件时,推荐使用busboy的流式处理,避免将整个文件加载到内存中。
  • 确保请求的Content-Type头部包含multipart/form-data及正确的boundary参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:05:06