typescriptfastifybusboy

Busboy with Fastify gives Unsupported Media Type: multipart/form-data; boundary


I'm trying to upload a file with BusBoy in Fastify

but I get this error

Unsupported Media Type: multipart/form-data; boundary=--------------------------964469693542161018443025
    reqId: "req-1"
    res: {
      "statusCode": 415
    }
    err: {
      "type": "FastifyError",
      "message": "Unsupported Media Type: multipart/form-data; boundary=--------------------------964469693542161018443025",
      "stack":
          FastifyError: Unsupported Media Type: multipart/form-data; boundary=--------------------------964469693542161018443025
              at ContentTypeParser.run 

The upload function looks like this....

import Busboy from "busboy";

async function uploadFile(fastify: any, _options: Object) {

  fastify.post(
    "/v1/uploads/uploadFile",
    postOpts,
    async function (request: any, reply: any) {
      const bb = Busboy({
        headers: request.headers,
        preservePath: true,
        limits: { fileSize: 100000 },
      });
      bb.on(
        "file",
        (
          fieldname: any,
          file: any,
          filename: any,
          encoding: any,
          mimetype: any
        ) => {
          console.log(fieldname, file, filename, encoding, mimetype);

          request.pipe(bb);
        }
      );
     

      const statusCode: number = 201;
      reply
        .code(statusCode)
        .header("Server-Timing", createServerTiming(serverTiming))
        .header("Content-Type", "application/json; charset=utf-8")
        .send({ statusCode });
    }
  );
}

const postOpts = {
  schema: {
    summary: "Upload File",
    consumes: ["multipart/form-data"],
    response: {
      200: {
        type: "object",
        description:
          "The request was successful. The response will contain a JSON body.",
        properties: {
          uploadConfirmed: { type: "boolean" },
        },
      },
      400: {
        type: "object",
        description: "The request was invalid and/or malformed.",
        properties: {
          error: { type: "string" },
          statusCode: { type: "number" },
          message: { type: "string" },
        },
      },
      500: {
        type: "object",
        description: "There was an internal error.",
        properties: {
          error: { type: "string" },
          statusCode: { type: "number" },
          message: { type: "string" },
        },
      },
    },
  } as const,
};

export { uploadFile };

docs for fastifty busboy here


Solution

  • The HTTP request parsing happens into the fastify's content-type parser component.

    You need to set it up like:

    fastify.addContentTypeParser('multipart', myBusboyImplementation)
    
    function myBusboyImplementation (request, payload, done) {
      // payload is the request stream where you can listen for `data` events
      done(null, 'my parsed payload')
    }
    

    Note that this is already implemented by @fastify/multipart but you can implement it at your convenience