Search code examples
jqueryruby-on-railspaperclip-validation

Checking file size/type before upload using Paperclip and Rails


I have a Rails app which allows users to upload videos (on a local, rather than a cloud, server).

I'm using Paperclip 3.1.4 and Paperclip-ffmpeg 0.9.0.

Everything is working fine and dandy, but the problem is that, if a user uploads a file in the wrong format, or greater than the size allowed by the validation rules, the error message is not displayed until after the upload has taken place - not great for usability, particularly if it takes 10 minutes to upload a file in the wrong format!

So, is there any way I can integrate, let's say, jQuery (which I'll admit to knowing very little about) into my model, so that the file can be checked as soon as the user hits the "Upload" button, rather waiting until the app has tried to upload the file (if that makes sense)?

Here's some code from my model (I've stripped the unimportant stuff):

class Video

     attr_accessible :sourcefile

     has_attached_file :sourcefile

     ...

     validates_attachment_size :sourcefile, :less_than => 250.megabytes, 
        :message => "Sorry, your video is too large"
     validates_attachment_content_type :sourcefile, :content_type => [...],
        :message => "Sorry, the file format is wrong"

end

So, is there any way I could "bolt on" a function to trigger some form of JavaScript to check the file before it is uploaded and these validation rules kick in place (which I'd like to keep on the off chance that the user has JavaScript disabled in their browser)?

It would also be good if there was another function I could use to trigger a jQuery-esque progress bar if the file type is correct, but that's not necessarily required at this stage.

Thanks!

EDIT - Thanks to Kevin B below who noted that jQuery/JavaScript cannot be used to check file sizes. Oh well! Is there any other approach I could take? The server is running nginx, but I'd rather not go there - I'd prefer to deal with the issue within the Rails code itself.


Solution

  • You can configure the maximum size of any request in nginx, and then have your jQuery code respond to the 413 status code that nginx will return if the file is too large. Nginx should be able to reject it immediately when it sees the request header rather than letting the user upload the whole file; your rails app will never see these requests, for better or worse.

    In your nginx config for the site, you'll want to set:

    client_max_body_size 250M;
    

    In your jQuery, you can specify an error callback that gets called if the request fails. In that callback, I use something like this:

        if (responseText.responseText.match(/413 Request Entity Too Large/)) {
            error_message = "Files cannot be more than 250 MB.";
        }
    

    After that, you just need to get the error_message where the user can see it. This method keeps overlarge files off your server regardless of whether javascript is turned on or not, but if JS is enabled, they can get nicer feedback. And for what it's worth, I'm using the jQuery form plugin to fake AJAX file uploads, but there are other ways to do that too if you want.