Rails - async image processing using fog and carrierwave_direct

My last blog post was about direct uploading image to S3 storage using Rails, fog and carrierwave. In most cases if you allow the user to upload images you will need to make various sizes of the uploaded image in order to display previews, thumbnails and smaller web versions across your application.

Image processing can be performance killer for your app. It depends on the image size and can make your app irresponsive until the manipulation process is finished.

That is why you might want to consider moving image processing to a background task. In this example I use DelayedJob for background processing. The interesting part is that I use background image processing along with carrierwave_direct and S3 storage.

If you read my previous blog post you will learn how to upload images directly to the S3 cloud. But this means that the original image is no longer stored on your server and processing it requires downloading it from the S3.

This is easily achievable using carrierwave_direct. All you need to do is to define custom action which will execute a simple background task. Here is how my background processing action looks like:

in the model

  def process_versions
    self.remote_image_url = self.image.direct_fog_url(with_path: true)
  handle_asynchronously :process_versions

Everything is handled by the carrierwave_direct gem. This will download the original image, then process all versions described in your carrierwave uploader and store them on the S3. All this in a nice background task. Of course you may want to set up some additional fields to indicate when the process is complete in order to show the user some feedback because until the background task is finished you won't be able to show your thumbnails since they still does not exists on the S3.

One important note: if you use fog with config.fog_public = false the above example will fail. This is because direct_fog_url(with_path: true) does not give you the access query parameters and your application actually can't download the original image because of access denied exception. This is a known bug which seems to be fixed already. However it is not working for me using version 0.0.14 of the carrierwave direct gem. My workaround is to change the permissions of the original uploaded file to public_read and overwrite them on versions store. So you need to define the acl of your upload form and generated file policy to public_read. Once image versions are up your original image permissions will be overwritten back to private.

Zlatan Zlatanov

About Zlatan Zlatanov

A developer who love learning new things, living and working at the shore of Black sea.

  • Writing from Varna, Bulgaria

comments powered by Disqus