Skip to content

How I proxyd a file upload through a Next JS middleware

a paper ball next to a paper plane

The short answer, it turns out that Axios knows what to do with a Buffer object.

I needed to upload a file from a browser to middleware through an API call, and then have the middleware also send said file to a service through an API call. The service expects the payload to be exactly the file data, no enveloping.

I own the middleware and client code and here’s the solution that I set up to correctly call the service API. This isn’t necessarily well researched but it works.

I read that the popular solution for handling file upload in Next.js land is to set up a Multer middleware with Next-Connect for simplified integration but I opted to just use Busboy to process the body payload. It turns out that Multer also leverages Busboy.

The Client

The client is expected to be a modern browser so I can assume the fetch interface to be present, although I might consider using Axios in the client to streamline with Node server coding. To bundle the image in my API call, I use FormData for convenience. I’ve discussed using FormData in the past as an AJAX version of submitting a form and it is well supported.

// get the File object from a file uploader event
const file =[0]

// use FormData to build the payload as multipart/form-data
const blobData = new FormData()
blobData.append('image', file)

// make api call with image payload
fetch(route, {
  method: 'POST',
  body: blobData,

The Middleware

The middleware runs on a Next.js server. For this example, assume the existence of the req argument. Next.js automatically processes the request body so I had to disable that to allow for Busboy to stream the data.

I struggled with extracting a correctly encoded image data payload in isolation but through experimentation I discovered that Axios knows what to do with a Buffer as a data argument.

// don't process the body - busboy will handle that
export const config = {
  api: {
    bodyParser: false

// process payload inside a request handler

// configure busboy to only look for one file
const busboy = new Busboy({
  headers: req.headers,
  limits: {
    files: 1

// process the request body and stream the file data
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
  const buf = []
  file.on("data", (d) => {
  ).on("end", async () => {
    const data = Buffer.concat(buf), data, {headers: {'Content-Type': 'image/*'}})

Wait, comments are loading...