Cloudinary Blog
Learn more...

Webhooks, upload notifications and background image processing

May 21, 2013 by Tal Lev-Ami
Web applications and web APIs are usually programmed to perform requests in a synchronous manner. A common web-based access flow will start with a requester accessing a remote service. The remote service in turn will process the request and quickly return the result. 
 
But sometimes a web application will need to perform actions asynchronously in the background. 
 
Consider, for example, a computing intensive web request. Such a request might take a very long time to finish. UI wise, you might not want your users to actively wait so long for this command to finish. Technically, such a long running HTTP request might even time-out completely. 
 
In this case, you will probably want to employ a different access flow. In this flow, when the requester accesses the remote service, the remote service will return immediately with a 'pending' result. The remote service will then continue to perform the action in the background. Finally, when the remote service is finished, it will notify the requester that the required action was completed. 
 
The same concepts apply to Cloudinary's image management APIs. 
 
So far, Cloudinarys APIs were synchronous. For example, if you wanted an image transformed, you would have to wait synchronously until the transformation was finished.
 
In this blog post we wanted to introduce Cloudinary's new notifications and background processing capabilities that further extend the image management solution available when using Cloudinary.
 

Webhooks and upload notifications

Many mobile and web applications upload images and files to Cloudinary. Such uploading can be performed either from these services' backend or directly from their users' browsers or mobile applications. In such cases you might want to make sure your server is notified when an upload is completed. 
 
You can do that by setting the notification_url parameter of Cloudinary's upload API to any valid HTTP (or HTTPS) public URL.
 
For example, in PHP:
$result = \Cloudinary\Uploader::upload("sample.jpg", 
   array("notification_url" => "http://mysite/my_notification_endpoint"));
When the upload is completed, an HTTP POST request will be sent to the notification URL you provided. The post data will contain all upload result details as returned by our upload API (public ID, URLs, image dimensions, semantic data if requested and more). The request will also contain a signature of the sent data so you can verify the sender.
 
Here's a sample POST request with a JSON of the upload result:
POST /my_notification_endpoint HTTP/1.1
X-Cld-Timestamp: 1368881627
X-Cld-Signature: 29a383e289bc569310a8ca9899019a3167b4909e
Content-Type: application/json

{"public_id":"djhoeaqcynvogt9xzbn9","version":1368881626,"width":864,"height":576,"format":"jpg","resource_type":"image","created_at":"2013-05-18T12:53:46Z","bytes":120253,"type":"upload","url":"http://res.cloudinary.com/1233456ab/image/upload/v1368881626/djhoeaqcynvogt9xzbn9.jpg","secure_url":"https://cloudinary-a.akamaihd.net/1233456ab/image/upload/v1368881626/djhoeaqcynvogt9xzbn9.jpg"}
By the way, you can use RequestBin to test notifications received during development.
 
The signature is calculated as follows:     
SHA1-Hex-Digest("{data}{timestamp}{api_secret}")
Your server application can use this notification to update your model and database regarding the uploaded images or to cleanup unused uploaded files.
 
Here's another example in Ruby on Rails for generating a file input field that performs direct uploading from the browser using a jQuery plugin.
<%= cl_image_upload_tag(:picture, 
      :notification_url => "http://mysite/my_notification_endpoint") %>

Eager transformations in the background

By default, when you access Cloudinary delivery URLs, transformed images are generated dynamically if they don't already exist, according to the transformation parameters. You can also use Cloudinary's eager transformations, in which case multiple transformed versions of an image are created eagerly while uploading so they are ready for fast delivery even for the first download request.
 
Sometimes, you might need to create a single time consuming transformation or many eager transformations of an uploaded image. Creating such transformations might take seconds, especially if the original image is very large. In such cases, you probably don't want your user to wait for the process to complete. 
 
Using Cloudinary's asynchronous eager transformations, you can now define multiple eager transformations while uploading. The upload request will return immediately, the transformations will be performed in the background by Cloudinary and you will get notified (if you want) when the transformations are ready.
 
You can enable asynchronous eager transformations by setting the new eager_async upload API parameter to true. In addition, you can set the optional eager_notification_url to receive an HTTP POST request when the transformation generation is completed.
 
The following example in Python (or Django) creates multiple transformations eagerly in the background.
cloudinary.uploader.upload("sample.jpg", 
   eager=[dict(crop="fill", width="150", height="100"), 
          dict(effect="sepia", width="0.5", crop="scale")], 
   eager_async=True, eager_notification_url="http://mysite/my_notification_endpoint")
Here's an example of how the notification post request might look like:
POST /my_notification_endpoint HTTP/1.1
X-Cld-Timestamp: 1368883736
X-Cld-Signature: 09ef8c16f6e0ff85f5345d4813973de8f746448d
Content-Type: application/json

{"batch_id":"c0ed79e610f0636d15a1353a0a866933","notification_type":"eager","eager":[{"width":150,"height":100,"url":"http://res.cloudinary.com/1233456ab/image/upload/c_fill,h_100,w_150/v1368883730/noapoaq60varndxnh2or.jpg","secure_url":"https://cloudinary-a.akamaihd.net/1233456ab/image/upload/c_fill,h_100,w_150/v1368883730/noapoaq60varndxnh2or.jpg"},{"width":432,"height":288,"url":"http://res.cloudinary.com/1233456ab/image/upload/c_scale,e_sepia,w_0.5/v1368883730/noapoaq60varndxnh2or.jpg","secure_url":"https://cloudinary-a.akamaihd.net/1233456ab/image/upload/c_scale,e_sepia,w_0.5/v1368883730/noapoaq60varndxnh2or.jpg"}]}


Background sprites, animated GIFs and PDFs handling 

Cloudinary supports generating sprites: merging multiple images into a single large image for a more efficient browser loading using a generated dynamic CSS. 
 
Sometimes you might want to merge tens or even hundreds of images into a single sprite. 
 
Cloudinary's image manipulation are fast and efficient, but transforming and merging so many images might take more that your API client request can wait. In this case an HTTP request timeout might occur.
 
You can now tell Cloudinary to perform such sprite generations in the background by setting the async API parameter to true. In addition, you can set the notification_url parameter for receiving a webhook request when the process is completed (as explained above).
 
The following Ruby example requests for a sprite generation to be performed in the background:
Cloudinary::Uploader.generate_sprite("faces", :width => 150, :height => 100, 
   :crop => :fill, :async => true, 
   :notification_url => "http://mysite/my_notification_endpoint")
 => {"status"=>"processing", "batch_id"=>"163a919cde8f9317d6ee0fbfe6375dc4"} 
The API returns immediately with the response below while the later notification will include the final generated sprite details:
POST /my_notification_endpoint HTTP/1.1
X-Cld-Timestamp: 1368882586
X-Cld-Signature: d91bccba5f1bb38905fc6a9284914e8959fb4a7b
Content-Type: application/json

{"batch_id":"f97c6bf03074d9641f1a9c9b6bcebef7","css_url":"http://res.cloudinary.com/1233456ab/image/sprite/c_fill,h_100,w_150/v1368882583/faces.css","image_url":"http://res.cloudinary.com/1233456ab/image/sprite/c_fill,h_100,w_150/v1368882583/faces.png","secure_css_url":"https://cloudinary-a.akamaihd.net/1233456ab/image/sprite/c_fill,h_100,w_150/v1368882583/faces.css","json_url":"http://res.cloudinary.com/1233456ab/image/sprite/c_fill,h_100,w_150/v1368882583/faces.json","version":1368882583,"image_infos":{"face_center_eer8ss":{"width":150,"height":100,"x":0,"y":0},"face_left_b7ikxf":{"width":150,"height":100,"x":152,"y":0},"face_top_usjwvk":{"width":150,"height":100,"x":0,"y":102},"front_face_cywiib":{"width":150,"height":100,"x":152,"y":102}},"notification_type":"sprite"}
You can now create an animated GIF or a multi-page PDF document in a similar fashion. 
 
You can also "explode" a PDF in the background into multiple separated images representing all of its pages. All this is done using Cloudinary's 'multi' and 'explode' methods by setting the async parameter to true and optionally setting a notification_url. Here are some examples in Ruby:
Cloudinary::Uploader.multi("faces", :format => 'gif', :width => 150, :height => 100, 
   :crop => :scale, :async => true, 
   :notification_url => "http://mysite/my_notification_endpoint")
Cloudinary::Uploader.explode("multi_page_pdf", :format => 'png', :width => 200, 
   :height => 300, :crop => :scale, :page => :all, :async => true, 
   :notification_url => "http://mysite/my_notification_endpoint")

Summary 

As always, our goal with Cloudinary is to solve all of your web and mobile app's image management and image manipulation aspects for you and let you focus on your core business logic.
 
As a developer, you are probably familiar with the complexities involved in managing background processing and push notifications yourself. We believe that Cloudinary’s new webhooks and the ability to perform computing intensive image manipulations asynchronously in the background will prove as very useful tools in your image management tool-belt.
 
We're anxious to hear your feedback about these new features. Make sure you drop us a line in the comment thread below!
 
blog comments powered by Disqus