Cloudinary Blog

How to build a real-time photo sharing website in a few easy steps

by Nadav Soferman
Two decades ago websites had such a simple usage flow. Web servers returned complete HTML pages and each user action required that a new HTML page be reloaded from the server. Later on Ajax joined the game allowing dynamic updating of specific web page fragments via simple Javascript requests to the server. Google's wide-spread use of Ajax with Gmail was simply mind blowing at the time. Today's product requirements wouldn't settle even for that.
 
Modern web and mobile applications demand interactive real-time experience. When a friend sends you an email in Gmail or a message with WhatsApp, you want these to pop up immediately, whether you're watching it on the relevant website or mobile application. When you browse through your Facebook news-feed, you want to see new Like events, new comments and new posts by your friends immediately as they happen, without waiting and without hitting 'refresh'.
 
If you are web developers, you are probably aware of the complexity of trying to implement real-time push notifications yourselves. Modern web frameworks and platforms allow you to easily build rich and dynamic web applications, but usually don’t include easy to use, scalable solutions for real-time interaction of web visitors and mobile app users. Therefore, if you haven't done so already, you should try out PubNub.
 
PubNub is a very powerful yet easy to use cloud service for real-time applications and push notifications. With a few lines of code you can extend your web and mobile apps with a fast, highly scalable solution for real-time notifications.
 

Photo sharing app - live demo

Cloudinary allows you to upload images to the cloud, manipulate these images, apply effects and delivering the images optimized through a fast, world-wide CDN.

PubNub allows sending real-time messages to a channel that multiple users can subscribe to. Cloudinary's image uploading can be performed directly from a visitor's browser or mobile application. Same goes for PubNub's messages subscription. 
 
Combining both cloud services, you can easily build a high-end, real-time photo sharing application. 
 
The flow is quite straightforward - use Cloudinary to allow your users to upload as many images as they want to the cloud and then send a message through PubNub to notify all other relevant users about these newly uploaded images. 
 
Recipients can ask Cloudinary to generate a scaled-down, cropped version of the original image to match their specific device and get that image delivered efficiently for best viewing experience.
 
All this can be done without any complex coding, complex deployment setup or CPU load on your side. You can focus on your core application while Cloudinary and PubNub take care of all your media handling and communication channels.
 
The following frame shows a live demo of a basic photo-sharing web app built using Cloudinary and PubNub. Try it out! Upload an image to Cloudinary directly from the browser, select a simple graphical effect to apply on it and share the photo using a PubNub message with all other users that currently view this page. See this in action by opening two desktop browsers or mobile devices simultaneously. All viewers subscribe to a single PubNub channel directly from the browser and display dynamic thumbnails and full size images, as they are being uploaded by all the other viewers.
 
Try it now:
 
 
A robust, highly scalable, highly available, feature rich real-time photo sharing application, with just a few lines of code. Cool, right?

How does it work? 

First of all, you can browse and copy all sources from GitHub: https://github.com/cloudinary/cloudinary_pubnub_demo
 
We used a thin Ruby server (Sinatra) for this demonstration. In addition to Ruby, Cloudinary and PubNub also offer integration libraries for PHP, Ruby on Rails, Python & Django, .Net, Node.js, iOS, Android and others.
 
1. First we embedded a file input field in the page. This field includes a signature generated on the server side for authorizing secure uploading to Cloudinary from the browser using Cloudinary's jQuery plugin. The following Ruby code embeds a signed input field. For more details see this post.
cl_image_upload_tag(:photo_id, :resource_type => :image,
                    :transformation => incoming_transformation)
The :transformation parameter in this example applies an incoming transformation before storing the image in the cloud. The specific incoming transformation we've used limits the image size and adds a watermark. 
 
Here's the definition of the incoming transformation in this live demo:
incoming_transformation = [ { width: 1200, height: 1200, crop: 'limit'},
                            { overlay: 'logos_watermark', width: 0.7flags: 'relative', opacity: 40, gravity: 'north', y: 20 } ]
In addition, custom styles for the input field and drag area as well as the uploading progress bar are implemented using CSS and jQuery (see source code).
 
 
2. When the user clicks on the Share button, an Ajax request with an identifier of the photo is sent to the server which securely publishes a message to our shared PubNub channel. 
 
The following server-side Ruby code receives the identifier and additional message details and publishes to a PubNub channel using PubNub's Ruby library:
preloaded = Cloudinary::PreloadedFile.new(params[:photo_id])         
pubnub = Pubnub.new( :publish_key => PUBNUB_PUBLISH_KEY:subscribe_key => PUBNUB_SUBSCRIBE_KEY )

pubnub.publish({
    :channel => PUBNUB_CHANNEL,
    :message => {
        cloudinary_photo_id: preloaded.identifier,
        user: params[:user],
        message: params[:message],
        kind: params[:kind],
        time: Time.now.utc.iso8601
    },
    :callback => lambda { |x| $stderr.puts("Shared #{preloaded.public_id}: #{x}") }
})

3. The client side code in the browser uses PubNub's Javascript library to subscribe to a PubNub channel for new messages. 
var pubnub = PUBNUB.init({ subscribe_key: PUBNUB_SUBSCRIBE_KEY});
pubnub.subscribe({ channel : PUBNUB_CHANNEL,
                   callback : show_message });
When a message is received, it includes the photo identifier which is the public ID of the image uploaded to Cloudinary. The following Javascript code uses Cloudinary's jQuery plugin to display a dynamically transformed, face-detection based thumbnail of the photo through a CDN. Once the image is clicked, the originally uploaded image (with a watermark) is shown.
function show_message(message) {
  var link = $('<a></a>').
    attr('href', $.cloudinary.url(message.cloudinary_photo_id)).
    append($.cloudinary.image(message.cloudinary_photo_id, 
               { width: 150, height: 100, crop: "fill",
                 gravity: "face", radius: 20, effect: "sepia"});
  $('.stream').prepend($('<li></li>').append(link));
}
In addition, a Javascript code fetches the recent 5 messages that were published before the page was loaded. This is done using PubNub's History support.
pubnub.history({
    channel  : PUBNUB_CHANNEL,
    limit    : 5,
    callback : function(history) { $.each(history, function() { show_message(this); })}
});
  

Summary

If you browse through this live demo's source code, you will notice that the few code lines listed in this blog post are actually almost everything you need to build your own, live photo sharing application.
 
PubNub's service was built by developers that understood that developers should use a fully featured and scalable solution for real-time notifications instead of trying to build one by themselves. Same goes for Cloudinary's service - developers should use a fully featured and scalable image management, manipulation and delivery service instead of spending precious time building one themselves.
 
Using both cloud-based services you can build complex, modern applications quickly, focus on the core of your application’s business logic and stop worrying about media management and communication channels anymore.
 
 
This demo is just one, simple example. It would be great to hear your feedback and learn about your own ideas in the comments thread below.

Recent Blog Posts

Dynamic ZIP files generation with a single line of code

As a developer, you want to allow your users to download multiple files in a single click. An easy way to download multiple files and share them is to generate a ZIP file. When images are involved, you may also want to normalize the original images before including them in the ZIP file, by scaling them down to the same maximum resolution or converting them to the same format.

Read more
How mindbodygreen reduce costs & save development time

mindbodygreen is a digital media brand dedicated to health and wellness. The company’s website bring together leaders in the wellness world, best-selling authors, fitness experts, trusted healers, pioneering doctors, top chefs, celebrities and top-tier journalists to provide readers fresh, expert content and tools to help them live healthy, happy lives. The company was founded in 2009 and is headquartered in Brooklyn, N.Y. 
Read more

Why JPEG is like a photocopier

by Jon Sneyers
Why JPEG is like a photocopier (generation loss)

If you make a copy of a copy of a copy, the quality will deteriorate with every ‘generation’. This problem is called ‘generation loss’. It is not difficult to understand why this happens with actual copier machines. Scanning and printing are not perfect, being based on noisy sensors and physical paper and ink, and the resulting noise will tend to accumulate.

Read more
Apply conditions to dynamically manipulate images.

It's great to have the capability to manipulate images on the fly by using dynamic URLs to customize the images to fit the graphic design of your site or mobile application. However, what if you want to manipulate an image depending on a specific image characteristic (like its width or aspect ratio) or its contents (does it contain a face?). What you need is a way to apply a transformation to an image only if a specific condition is met. Take for example a situation where you have allocated space on your page for a user uploaded image with a width and height of 200 pixels. Furthermore, if the image contains a face you would like to zoom in and focus on the face itself, otherwise you would like to fit the entire image into the available space:

Read more
Moviepilot focus on core business and reduce costs
 
Moviepilot Inc. is a media company that hosts a website and social publishing platform designed to bring together movie and TV fans, and help studios trigger, fuel and amplify positive conversations about entertainment topics. The site invites fans to create content, such as writing articles and producing videos, which are then curated on the site and distributed to more than 30 million fans worldwide. The site boasts more than 20 million unique visitors per month, with 87 percent of visitors accessing the site on mobile devices. The company is headquartered in Venice Beach, Calif., and has an office Berlin, Germany, where it was originally founded.
Read more