One of the features recently introduced in Ubuntu One and hidden beneath the covers is what we refer to as Magic Uploads. Recently this feature was also enabled in the REST API so I would like to demonstrate how this works.
But first What is a MAGIC Upload? a magic upload is the ability to save time when uploading a file you have uploaded in the past. This is done by including the hash of the file in the upload, if Ubuntu One detects you have previously uploaded that hash, it will not require an upload and just create the file. Magic hashing is an additional way to do this for files uploaded to Ubuntu One by anyone. This is done by including the hash of the file along with a magic hash which is calculated on the hash of the file. This may sound sophisticated, but it’s not, here’s a function that returns the hash of the file along with the so-called magic hash:
def get_u1_hashes(filename):
"""Calculate the file hashes used to update a file."""
hash_object = sha1()
magic_hash_object = sha1('Ubuntu One')
with open(filename, 'rb') as f:
content = f.read()
hash_object.update(content)
magic_hash_object.update(content)
hash = 'sha1:' + hash_object.hexdigest()
magic_hash = 'magic_hash:' + magic_hash_object.hexdigest()
return hash, magic_hash
As you can see, there’s no real magic. But in order to calculate the hash, you will need the content of the file. Note this is no trade secret I’m revealing here, it’s right there in the source for the Ubuntu One Storage Protocol used by the client. So how can you use this in the REST API?
Recently hash and magic_hash parameters were added to the PUT file API although as of this writing they are not documented in the public documentation. Note that this is different than the Content URI to put file content and upload a file. Here’s how the documentation should eventually include:
PUT /api/file_storage/v1/~/path/to/volume/path/to/node
Create, or change a file with existing content that was already uploaded.
{ "kind": "file", "hash": "<sha1 hash of file>", "magic_hash": "<magic hash>", }
And that’s it. Note that this feature has already been added to my Restful Ubuntu One client. So how can you take advantage of this? See my next post.