Wednesday, 13 February 2008

Upload progress bar by streaming JSON

Have you ever dealt with the problem of making an upload progress bar?
If you did, then it's time to continue reading.

I wanted to make one using javascript.
Basically, there are two alternatives:
  • The simpler one is to make periodic ajax requests to a url. That url must return the received_size/ total_size pair. All you need to do is to update your progress bar in the browser. This solution works in all those browsers which support AJAX. The disadvantage is that the browser will usually receive the (received_size/totoal_size) data pair delayed. So the progress bar won't show you the real progress.
  • The second option would be to use streaming. Instead of periodically polling the server, we should make one single request, and the server would stream the receive_size/total_pair data back to the browser.
I like this streaming alternative much more because it gives you a better UI experience.
Let me give you some hints on the streaming alternative.
  • The simplest and the secure way is to stream sequences of '<script type='text/javascript'>updateProgressBar(total, received)</script>' back to the browser. The returned javascript will be automatically executed in IE 6.0, Firefox, Safari and Opera. You can find a solution for this at Ry Dahl's article. However it works in a lot of browsers it's not the most elegant solution because you need to hardcode updateProgressBar in the server configuration file.
  • A little bit more elegant solution is to stream JSON expression like {"total_size": 10, "received_size": 0}; {"total_size": 10, "received_size": 1}; {"total_size": 10, "received_size": 2}; ...
If you are streaming JSON expressions you need to write a javascript function which updates the progress bar according to the last JSON slice. You can do this using this javascript utility. This script periodically checks the received content and calls your updateProgressBar function passing the last received JSON slice to it. Unfortunately this script doesn't works with the latest prototype library.

The shortest and the most elegant alternative is to use the "onInteractive" AJAX callback function. By using this callback we don't need to periodically check the response. It is called every time when new data arrives to the browser.
Look at this beautifull code:
new Ajax.Request('/upload/progress', {
pos :0,
onInteractive: function(obj) {
var slice = obj['responseText'].slice(this.pos)
var jsonFormat = slice.substring(0,slice.length - 2);
var json = jsonFormat.evalJSON();
updataProgressBar(json.totalSize, json.receivedSize);
this.pos = obj['responseText'].length + 1;

Unfortunately this callback doesn't work in Opera neither in IE.
And I didn't find any w3 recommendation for enforcing the browsers to implement it. :(

Let me summarize the opportunities and how are they supported on different browsers:

Opera latestFirefox 6IE 7
Periodic Ajax callsokokokokokok
Streaming <script> tagsokokokokokok
Streaming JSON, using Ry's javascriptokokokoknot workingnot working
Streaming JSON, using onInteractionnot workingokoknot workingnot workingnot working

So I need to keep up hacking till AJAX standard is born and implemented... :))

Saturday, 2 February 2008

Social Networking Softwares

I received an invitation to a "social network" software from India not long time ago.

I always subcribe to these software at least to check what are they capable of. I also like to observe the Darwinian evolution of software.

This software made me upset right in the first turn. It didn't harvest my relationships organically like FACEBOOK but it wanted to record my relationships using my Gmail contacts by borrowing my Gmail password. I didn't have any other choice if I wanted to see the web-app running, however borrowing my Gmail password was very suspicious to me. In the next step it enlisted all my Gmail contacts. There was a tiny checkbox to send the invitation to all of them or not. I didn't want to invite anybody to this social network, all I wanted to do is to check what it offers. Therefore I've unchecked the checkbox and went to the next page. Well... The service didn't offer me any excepcionally good quality. It was nothing to learn. So it didn't worth borrowing my precious Gmail password. For the sake of security I changed my Gmail password promptly.

I was surprized when many of my friends sent me a message in the next few days that they don't want to subscribe to this at all, nevertheless I unchecked the invitation checkbox. There were some of them who thought that this software is a VIRUS. Well I've unregistered myself from this "social networking" immediately

Well... This happens when a software harvests its users in an agressive manner rather than adapting the strategy to grow organically. The problem with it is that even sometimes even those people will be harvested who are not even my friends (I send them only one or two email messages in my whole life). So my "social network" will contain some foreign people to.

This precious information is now free and available for everyone, thanks to these softwares. But sometimes they also contain false relationships :)