Wednesday, August 27th, 2008

YouTube Uploader now using Gears, and what people missed in Gears 0.4

Category: Gears

<p>

While we posted about the Gears 0.4 features a lot of the press only really talked about the Geolocation piece.

I think that is important, and posted on that too, but Brad’s piece discussed the full gamut including the Blob API, resummable HTTP, and Desktop API improvements to allow controlled file system access. The example that Brad built was the upload movie tool which ties this all together.

Check out the source code and you will see the parts and pieces in action:

Geolocation

javascript
< view plain text >
  1. MovieTool.prototype.getLocation = function(callback) {
  2.   var geolocation = google.gears.factory.create('beta.geolocation');
  3.   if (!geolocation.getPermission('Upload Movie Tool', '',
  4.                                   'This sample can use your '
  5.                                 + 'geographic coordinates in order to tag '
  6.                                 + 'uploaded videos with your location')) {
  7.     document.getElementById('location').innerHTML = 'Permission denied';
  8.     callback();
  9.     return;
  10.   }
  11.  
  12.   var self = this;
  13.   geolocation.getCurrentPosition(
  14.     function(p) {
  15.       var addr = p.gearsAddress;
  16.       var address = addr.city + ', ' + addr.region + ', ' + addr.country;
  17.       var latitude = p.latitude;
  18.       var longitude = p.longitude;
  19.       self.geoAddress_ = address + ' (' + latitude + ', ' + longitude + ')';
  20.       document.getElementById('location').innerHTML = self.geoAddress_;
  21.       callback();
  22.     },
  23.  
  24.     function(err) {
  25.       var msg = 'Error retrieving your location: ' + err.message;
  26.       document.getElementById('location').innerHTML = msg;
  27.       callback();
  28.     },
  29.    
  30.     {
  31.       enableHighAccuracy: true,
  32.       gearsRequestAddress: true,
  33.       gearsLocationProviderUrls: ['http://www.google.com/loc/json']
  34.     }
  35.   );
  36. }

HTTPRequest

javascript
< view plain text >
  1. var req = google.gears.factory.create('beta.httprequest');
  2.   req.open('GET', '/list');
  3.   var self = this;
  4.   req.onreadystatechange = function() {
  5.     if (req.readyState == 4) {
  6.       if (req.status == 200) {
  7.         var loadingMsg = document.getElementById('loadingFilesMsg');
  8.         loadingMsg.parentNode.removeChild(loadingMsg);
  9.         self.movieList_ = eval(req.responseText);
  10.         for (var i = 0; i < self.movieList_.length; i++) {
  11.           var entry = self.movieList_[i];
  12.           // associative entry for fast lookup based on filename
  13.           self.movieList_['_' + entry.filename] = entry;
  14.           var status = 'Uploaded'
  15.           var percent = '100%';
  16.          
  17.           // was this movie partially uploaded during an earlier browser
  18.           // session?
  19.           if (entry.uploaded == false && entry.blob == null) {
  20.             status = 'Partially uploaded; re-select file to continue uploading';
  21.             percent = Math.round((entry.bytesUploaded / entry.length) * 100) + '%';
  22.           }
  23.          
  24.           // is this movie too large?
  25.           if (entry.uploaded == false && entry.length > self.MAX_FILE_SIZE) {
  26.             status = 'File too large';
  27.             percent = 'N/A';
  28.           }
  29.          
  30.           self.drawRow(entry.filename, entry.geoAddress, status, percent);
  31.         }
  32.       }
  33.      
  34.       callback();
  35.     }
  36.   }
  37.  
  38.   req.send();
  39. }
  40.  
  41. ....
  42.  
  43. // sending a piece
  44.   req.open('POST', uploadURL);
  45.  
  46.   req.setRequestHeader('Content-Disposition',
  47.                         'attachment; filename="' + fileName + '"');
  48.   req.setRequestHeader('Content-Type', 'application/octet-stream');
  49.   req.setRequestHeader('Content-Range', 'bytes ' + byteRange);

Desktop API

javascript
< view plain text >
  1. MovieTool.prototype.selectFiles = function() {
  2.   var desktop = google.gears.factory.create('beta.desktop');
  3.   var self = this;
  4.   desktop.openFiles(
  5.     function(files) {
  6.       for (var i = 0; i < files.length; i++) {
  7.         var entry = {filename: files[i].name, uploaded: false,
  8.                             length: files[i].blob.length,
  9.                             blob: files[i].blob, bytesUploaded: 0,
  10.                             geoAddress: self.geoAddress_, uploadRetries: 0};
  11.         if (self.movieList_['_' + entry.filename]) {
  12.           // was previously uploaded at an earlier browser session
  13.           var oldEntry = self.movieList_['_' + entry.filename];
  14.           if (!oldEntry.uploaded) { // partial upload
  15.             oldEntry.length = entry.length;
  16.             oldEntry.blob = entry.blob;
  17.             var percent = Math.round((oldEntry.bytesUploaded / oldEntry.length) * 100);
  18.             self.updateStatus(oldEntry.filename, 'Not uploaded', percent + '%');
  19.           } else {
  20.             self.updateStatus(oldEntry.filename, 'Uploaded', '100%');
  21.           }
  22.         } else { // new file
  23.           // associative entry for fast lookup based on filename
  24.           self.movieList_['_' + entry.filename] = entry;                    
  25.           self.movieList_.push(entry);
  26.          
  27.           var status = 'Not uploaded';
  28.           var percent = '0%';
  29.           // is this movie too large?
  30.           if (entry.length > self.MAX_FILE_SIZE) {
  31.             status = 'File too large';
  32.             percent = 'N/A';
  33.           }
  34.          
  35.           self.drawRow(files[i].name, self.geoAddress_, status, percent);
  36.         }
  37.       }
  38.      
  39.       document.getElementById('movieUpload').disabled = false;
  40.       document.getElementById('clearMovies').disabled = false;
  41.     },
  42.    
  43.     { filter: ['video/quicktime', '.wmv', 'video/avi'] }
  44.   );
  45. }

It turns out that YouTube has implemented a multifile upload using Gears which puts this into practice. As someone who uses YouTube a lot to upload files this is very welcome indeed, and I can’t wait to see more sites use it now the building blocks are there in a different way (can always use Flash / other controls in the past).

Related Content:

Posted by Dion Almaer at 9:20 am
2 Comments

++++-
4.1 rating from 16 votes

2 Comments »

Comments feed TrackBack URI

Hmm, a free, open, probably highly accurate and often updated geolocation api that probably has decent response time. I think maxmind is going to lose some business eventually.

I can’t get the demo code to work unfortunately, I may have google too heavily filtered and firewalled (big brother and all)

here’s the svn http://google-ajax-examples.googlecode.com/svn/trunk/uploadmovietool/

Comment by ck2 — August 27, 2008

Hi ck2, what browser are you using? Do you have Firebug installed? Take a look at the output there and tell me what message or exception you see. Sometimes the Geolocation API will return that it can’t find a location, especially if you are on a private Wifi network that has not been mapped.

Comment by Brad Neuberg — August 27, 2008

Leave a comment

You must be logged in to post a comment.