Best way to limit the total size of files uploaded?

silverstripe-4
Tags: #<Tag:0x00007f083115e420>

#1

Hi all,

I am working on a project, where the client needs to be able to restrict files that are uploaded based on who is logged in.

Basically, some users have a “quota” (total allowed upload size). If the user tries to upload a file (or files) that exceed this limit, then the files are rejected and an error is sent to the user.

Currently I am thinking of doing this by:

  1. Creating a new version of UploadField and overwriting UploadField::upload() (which will flag an error if the upload is too large).

  2. Also extending File::onBeforeWrite() to flag an error (or raise an exception) somehow.

I was wondering if anyone had any pointers? Are the points above the best approach? I am not 100% about if point 2 will work…

Cheers,

Mo


#2

I think that could work. My approach though would probably be to tie this behaviour to the specific form where this upload is happening, as custom validation logic. I guess you would essentially let the upload proceed normally, then do your size checks and delete the uploaded file if necessary, and return the user to the form with an error message.

This could be frustrating for the user, so I would also use javascript to check the size of selected files in the front-end before the upload starts, and show a warning and block submitting of the form if the size will cause a user to exceed their limits. DropZone was a drop-in solution for this in SS3 (and you could configure that with an applicable max filesize base on user quota in your php code), don’t know if there is an equivalent for SS4 yet but I think you should be able to achieve similar with a little bit of custom JS and a hidden field that passes the available upload quota to the front-end.


#3

Hmm, OK, thanks for the response. I did think about using a custom validator, but as Assets in SS4 uses React, I wasn’t sure if/how possible it would be to do this.

Adding some JS to the frontend would be nice, but again, wouldn’t this need to be React (I could do what you suggest quite easily in Entwine)?


#5

So after a LOT of time messing about with React, I gave up and just created my own Upload_Validator and then used Dependency Injection (https://docs.silverstripe.org/en/4/developer_guides/extending/injector/) to swap out the default.

This works pretty well, but as you say @JonoM the user has to upload the file first before getting an error. I would prefer to add a JS version as well, but the reality os (for this project) most users will be uploading files no more than a few MB in size, so having to wait to upload is not that much of an issue (though I am also adding several visual indicators to show how much space is left).


#4

Sorry, I assumed you were talking about a front-end website form. If you’re talking about the CMS then yes, customising the front-end asset experience is quite a bit more technical. You could look at the FocusPoint module for a reference perhaps, @bummzack updated it to integrate with the React layer.

You can still easily add new fields to the asset form with php (although not with getCMSFields :face_with_raised_eyebrow:) so you could maybe add a little message showing how much quota a user has left at least, particularly if it’s running low.

You should be able to access the UploadField with an updateFormFields extension hook for SilverStripe\AssetAdmin\Forms\AssetFormFactory. Then you could look at how much quota the current user has that’s available, and if it’s less than the global default/maximum upload size, you can reduce the allowed file size for that field and post a warning. Something like:

$uploadField->getValidator()->setAllowedMaxFileSize($size)->setDescription("Warning: your quota is close to full so you can only upload a field up to $niceSize in size.");