koajs / bodyparser

Koa body parsing middleware
MIT License
1.31k stars 116 forks source link

Uploading blob via XMLHttpRequest #101

Closed daviestar closed 6 years ago

daviestar commented 6 years ago

Apologies if this is the wrong place to ask this... but I haven't been able to get anywhere with it and would be very grateful if a knowledgeable person could point me in the right direction...

I currently upload images direct to Amazon S3 like so:

const fileUploader = async (url, file) => {
  const xhr = new XMLHttpRequest()

  xhr.addEventListener('readystatechange', () => {
    // ...
  })
  xhr.upload.addEventListener('error', () => {
    // ...
  })
  xhr.upload.addEventListener('abort', () => {
    // ...
  })
  xhr.upload.addEventListener('progress', () => {
    // ...
  })

  xhr.open('PUT', url)
  xhr.setRequestHeader('content-type', file.type)
  xhr.setRequestHeader('x_file_name', file.name)
  xhr.send(file)
}

and I'd like to create an endpoint in Koa to replicate this type of file upload for development and tests. When I try, the body is always an empty object:

router.put('/image-upload', bodyParser(), async(ctx) => {
  console.log(ctx.request.body) // {}
})

I can see from Chrome DevTools that the request body is binary data.

content-type is image/jpeg.

Any advice greatly appreciated!

dead-horse commented 6 years ago

bodyparser will only parse the json or form data, maybe you should try https://github.com/stream-utils/raw-body to get the raw request body.

daviestar commented 6 years ago

Thankyou @dead-horse !

Here's some working code in case anyone else lands here:

import getRawBody from 'raw-body'

router.put('/image-upload', async (ctx) => {
  const file = await getRawBody(ctx.req)
  const bufferStream = new stream.PassThrough()
  const writeStream = fs.createWriteStream(`${config.staticDir}/file.jpg`)
  bufferStream.end(file)
  bufferStream.pipe(writeStream)

  ctx.body = {
    status: 'uploaded!'
  }
})