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

Fastify集成BusBoy上传文件报Unsupported Media Type错误求助

解决Fastify中使用BusBoy上传文件时的415 Unsupported Media Type错误

错误原因

Fastify默认未配置multipart/form-data类型的请求解析器,当收到该类型请求时会直接返回415错误。同时你的代码存在几处逻辑问题需要调整。

解决方案

1. 禁用Fastify自动解析请求体

在路由配置中添加parse: false,阻止Fastify自动解析请求体,让BusBoy直接处理原始请求流:

const postOpts = {
  parse: false, // 关键:禁用自动解析
  schema: {
    summary: "Upload File",
    contentType: 'multipart/form-data', // Fastify v4推荐用contentType替代废弃的consumes
    response: {
      201: { // 对应实际返回的201状态码
        type: "object",
        description: "文件上传成功",
        properties: {
          statusCode: { type: "number" },
          uploadConfirmed: { type: "boolean" }
        },
      },
      400: {
        type: "object",
        description: "请求无效或文件不符合要求",
        properties: {
          error: { type: "string" },
          statusCode: { type: "number" },
          message: { type: "string" },
        },
      },
      500: {
        type: "object",
        description: "服务器内部错误",
        properties: {
          error: { type: "string" },
          statusCode: { type: "number" },
          message: { type: "string" },
        },
      },
    },
  } as const,
};

2. 修正BusBoy的使用逻辑

  • 将request.pipe(bb)移到事件绑定之外,确保请求流被及时捕获
  • 用Promise包裹异步处理逻辑,等待文件上传完成再返回响应
  • 补充错误处理,避免请求挂起

修改后的路由处理函数:

import Busboy from "busboy";

async function uploadFile(fastify: any, _options: Object) {
  fastify.post(
    "/v1/uploads/uploadFile",
    postOpts,
    async function (request: any, reply: any) {
      return new Promise((resolve, reject) => {
        const bb = Busboy({
          headers: request.headers,
          preservePath: true,
          limits: { fileSize: 100000 },
        });

        // 处理文件流
        bb.on("file", (fieldname, file, filename, encoding, mimetype) => {
          console.log(`收到文件:${filename},字段名:${fieldname}`);
          // 这里可添加文件存储逻辑,比如写入磁盘或云存储
          file.on('data', (chunk) => {
            // 处理文件数据块
          });
          file.on('end', () => {
            console.log(`文件 ${filename} 接收完成`);
          });
          file.on('error', (err) => {
            reject(new Error(`文件处理失败:${err.message}`));
          });
        });

        // 上传完成后返回响应
        bb.on("finish", () => {
          resolve(
            reply
              .code(201)
              .header("Server-Timing", createServerTiming(serverTiming))
              .header("Content-Type", "application/json; charset=utf-8")
              .send({ statusCode: 201, uploadConfirmed: true })
          );
        });

        // 捕获BusBoy错误
        bb.on("error", (err) => {
          reply.code(400).send({ 
            error: err.message, 
            statusCode: 400, 
            message: "文件上传失败" 
          });
          reject(err);
        });

        // 将请求流导入BusBoy
        request.pipe(bb);
      });
    }
  );
}

关键注意点

  • Fastify v4已废弃consumes字段,改用contentType指定请求类型
  • BusBoy的处理是异步的,必须用Promise包裹,确保Fastify等待处理完成再响应
  • 务必处理文件流和BusBoy的错误事件,避免出现未捕获异常导致请求挂起

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:45:45