opensource icon indicating copy to clipboard operation
opensource copied to clipboard

Anyways to set the file size limit for the `multipart/form-data`?

Open zypeh opened this issue 8 years ago • 6 comments

I see there is a common problem with formidable, just want to know is there a way to deal with file size limitation by the bytesReceived from form.progress ?

zypeh avatar Sep 24 '16 11:09 zypeh

Don't know what you mean. What problem? And what you're want to do? Is it just a question as I may be more familiar with formidable, or it is something formidable-related bug?

tunnckoCore avatar Sep 24 '16 17:09 tunnckoCore

My bad, I just want to know is that a way to do the file size limitation from multipart/form-data ?

Anyway, I have made some dirty hack for my project. But what I want is to throw an error and close the connection when the user's upload file exceed certain limit.

zypeh avatar Sep 24 '16 18:09 zypeh

Got it. Hm... I'll think, but why not just pass IncomingForm instance? And before that add listener on the file event, than you can just throw.

Something like that, could you try?

var form = new formidable.IncomingForm()
form.on('file', function (name, file) {
  if (file.size > myAppConfig.maxFileSize) {
    throw new Error('file sieze exceeded: ', JSON.stringify(file))
  }
})
app.use(body({
  multipart: true,
  IncomingForm: form
}))

That was the reason behind v2 and v3, decoupling.

edit: That fileLimit is a bit good idea. If something around above doesn't work, I can think to implement something. We can add check that checks file.size against opts.textLimit?

tunnckoCore avatar Sep 25 '16 00:09 tunnckoCore

I opened and feature issue for that (it make sense and cost nothing), but you can still try my snippet.

tunnckoCore avatar Sep 25 '16 00:09 tunnckoCore

Um... I tried that before and I know it works, but plain throw new error are not a good way for my project since what I want is error propagation. I want to return a JSON result with error message, thus I got to:

  • Modify the context, or
  • Error that can be catch by koa instance

I was thinking about using form.on('progress') event listener. Which is something like this:

form.on('progress', function(byteReceived, byteExpected) {
  if (byteReceived > options.fileLimit) {
    fields = buff && buff.length
    ? utils.extend({}, utils.parseQs(buff.slice(0, -1), options), fields)
     : fields

    throw new Error('Exceed file size limit')
    // or 
    fields['_ERROR'] = 'too big'
    done(null, {
       fields: fields,
       files: files
    })
}

it can check from the byteReceived which is more precise. Just my two cents.

zypeh avatar Sep 25 '16 09:09 zypeh

Hm. I think to implement it in some way. Listening on progress event is good idea, but it is for fields too, so i would be more tricky.

So i think to add a check in file event that checks file.size against options.fileLimit and if so, add an object with error property instead of a file object. So you can access it again by name, but if there is .error so you can throw or do what you want.

form.on('file', (name, file) => {
  if (file.size > options.fileLimit) {
    files.push({ error: new Error('Exceed file size limit') }
  } else {
    files.push(file)
  }
})

form.on('end', () => {
  done({
    fields: fields,
    files: files
  })
})

so later in the middlewares you can

app.use((ctx, next) => {
  ctx.request.files.forEach(file => {
    if (file.error) return ctx.throw(file.error.message);
    console.log("file:", file);
  });
});

tunnckoCore avatar Jul 16 '17 12:07 tunnckoCore