Upload a file is a common action for websites. And CarrierWave gem provides a very simple and flexible way to achieve that for Rails application.

In realistic situation, you may only allow user to upload files within a limited size or with certain type. For example, only image file type (extension .jpg .jpeg .gif .png) with 5 MB maximum size is allowed. Below, I will show you how to do validations for file size and file extensions.

The validations should be implemented on both front end (client side) and back end (model level). Here I assume you already created  an User model, and a string field :avatar to mount the uploader of CarrierWave, following this guide.

1. Client Side Validation

The front end side (client side) is implemented using jQuery.

First, we need to create a file field inside of your form, using Rails’ file field helper:

<%= f.file_field :avatar,:onchange =>"validateFiles(this);",
:data => {
:max_file_size => 5.megabytes
}%>

Here, onChange event is triggered when file is selected, and method validateFiles is called. And notice that I create a data attribute “max_file_size” to store the maximum allowed file size information. You can change this value to suit your needs.

Then, we need to implement the validateFiles method. Put the following javascript code inside of your .js file:

function validateFiles(inputFile) {
  var maxExceededMessage = "This file exceeds the maximum allowed file size (5 MB)";
  var extErrorMessage = "Only image file with extension: .jpg, .jpeg, .gif or .png is allowed";
  var allowedExtension = ["jpg", "jpeg", "gif", "png"];
 
  var extName;
  var maxFileSize = $(inputFile).data('max-file-size');
  var sizeExceeded = false;
  var extError = false;
 
  $.each(inputFile.files, function() {
    if (this.size && maxFileSize && this.size > parseInt(maxFileSize)) {sizeExceeded=true;};
    extName = this.name.split('.').pop();
    if ($.inArray(extName, allowedExtension) == -1) {extError=true;};
  });
  if (sizeExceeded) {
    window.alert(maxExceededMessage);
    $(inputFile).val('');
  };
 
  if (extError) {
    window.alert(extErrorMessage);
    $(inputFile).val('');
  };
}

Basically, this code will check if the input file is over the limit and if the input file type is included in the array allowedExtension. Alert window will pop up when validations fail, and the input field will be cleaned.

You can customize the error messages by change the values of maxExceededMessage and extErrorMessage, also you might want to change the allowed file extensions by changing the allowedExtension array.

That’s it for the client side!

2. Model Level Validation

Now, we need to add the same validation on the model level. For file extension check, you just need uncomment the extension_white_list method existing inside of your uploader class:

class AvatarUploader < CarrierWave::Uploader::Base
 
... ...
 
  def extension_white_list
    %w(jpg jpeg gif png)
  end
end

Furthermore, the validation for file size is done by Rails custom validator. Inside of User model, add the following code:

class User < ActiveRecord::Base
  ... ...
  validate :avatar_size_validation
 
  ... ...
  private
 
  def avatar_size_validation
    errors[:avatar] << "should be less than 5MB" if avatar.size > 5.megabytes
  end
end

And that’s it!

4 Thoughts on “Validate Attachment File Size and Type in Rails

  1. validation of size with carrierwave doesn’t work for me :( i use Rails 4

  2. why? What is the error?

  3. This was a huge help to me and it works perfectly, thanks!

Leave a Reply

Post Navigation