Skip to content

Instantly share code, notes, and snippets.

@jeffijoe
Last active September 1, 2023 07:34
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jeffijoe/60c7a1fbf36a767477c82b9fe651fe48 to your computer and use it in GitHub Desktop.
Save jeffijoe/60c7a1fbf36a767477c82b9fe651fe48 to your computer and use it in GitHub Desktop.
Streaming uploads through Koa.
import Koa from 'koa'
import parse from './busboy'
import AWS from 'aws-sdk'
const app = new Koa()
const s3 = new AWS.S3({
params: { Bucket: 'myBucket' }
})
// Assuming this is a route handler.
app.use(async (ctx) => {
const { file, filename } = await parse(ctx.req)
// `file` is a Stream. Pass this to S3, Azure Blob Storage or whatever you want.
// `filename` is the file name specified by the client.
const result = await s3.upload({
Key: filename,
Body: file
}).promise()
ctx.body = result
})
import Busboy from 'busboy'
/**
* Parses a single file from a Node request.
*
* @param {http.IncommingRequest} req
* @return {Promise<{ file: Stream, filename: string>}
*/
export default function parse (req) {
return new Promise((resolve, reject) => {
const busboy = new Busboy({
headers: req.headers,
limits: {
files: 1 // allow only a single upload at a time.
}
})
busboy.once('file', _onFile)
busboy.once('error', _onError)
req.pipe(busboy)
function _cleanup () {
busboy.removeListener('file', _onFile)
busboy.removeListener('error', _onError)
}
function _onFile (fieldname, file, filename) {
_cleanup()
resolve({ file, filename })
}
function _onError (err) {
_cleanup()
reject(err)
}
})
}
// `file` is a DOM File object.
function upload (file) {
const data = new window.FormData()
data.append('file', file, file.name)
return axios.post('/upload', data)
}
@akellbl4
Copy link

Thanks, this is really handy for me.
But I have one question: Why do you remove listeners after handling event? Firstly you subscribe on once, secondly your function must be garbaged after run. Or am I wrong?

@jeffijoe
Copy link
Author

jeffijoe commented Dec 17, 2018

@akellbl4 because the events are mutually exclusive, so if one triggers the other won't, and you might risk a dangling handler. This might be unnecessary, but I do it just in case. Better safe than sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment