Resumable Downloads with AIR

I`m just developing an AIR project were the client needs to be able to synchronize big loads of data. So I thought it would be cool if the user can pause and resume downloads.
I first thought that this would not be possible but then i looked at the Adobe Media Player and he does it as well (Look into the Download Manager). The trick seems to be easy.
After a quick search through the Http specification i found out that you can write a custom header to use with the URLStream class. With Http specification 1.1 you can define a range of bytes you want to download so you don`t have to start from the beginning.
Here is how a sample Request looks like:
GET /files/richflv/help/ExportOptions.flv HTTP/1.1
Referer: app-resource:/LoadingTest.swf
x-flash-version: 9,0,60,153
Range: bytes=1200000-1300000
User-Agent: Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0
Host: www.richapps.de
In Actionscript we can write a custom header like this:
var header1:URLRequestHeader = new URLRequestHeader(”range”,”bytes=”+currentBytesPosition+”-”+toRange);
var re:URLRequest = new URLRequest(downLoadURL);
re.requestHeaders.push(header1);
currentBytesPosition = toRange;
urlStream.load(re);

This should work with most servers/files. To make sure it works you can first make a request and analyse the response header. It should include something like this:
Accept-Ranges: bytes

I think you get the idea! This is pretty powerfull especially if you want to synchronize big chunks of binary data and the client closes the client in between.
On the next startup you can simply resume  the download at the position were the client closed your AIR app. There are so many hidden goodies in AIR/AS3.0!

Comments

15 Responses to “Resumable Downloads with AIR”

  1. 1 on October 31st, 2007 2:40 pm

    Nice Soft

  2. Mudit on November 10th, 2007 12:09 pm

    This is a really good find.
    I wonder can this be employed to progressively download a FLV(not from the start) into a flash video player.

  3. Jason Nussbaum on November 13th, 2007 11:20 pm

    I was looking into this today, as well. The documentation for the URLRequestHeader class states that there is a list of headers that are not allowed; included in this list was the “range” header. Do you know if this is allowable specifically in AIR, or if the documentation is plain wrong?

    As for using this to progressively load an FLV – this is the tactic Google Video or YouTube uses (can’t remember which, might be both now) to allow seeking within a progressively loaded FLV, even to places in the FLV that haven’t been loaded.

  4. Benjamin (Admin) on November 14th, 2007 1:30 pm

    Progressive download is possible with flv files out of the box you don`t need this header stuff for this. Using my technique for progressive download would not work because currently it`s not possible to pass bytes to the NetStream/Video classes. This is just interesting for downloading stuff.

    @Jason: I`ve not tested if it works in the flash player but i can imagine that it only works in AIR.

  5. Christian Pfeil on November 22nd, 2007 8:19 am

    You are crazy man! Keep on going. Would be nice if you come up with a sample application to show how the whole stuff works.

    regards,

    Christian

  6. Chrisz on December 10th, 2007 8:07 pm

    Hallo Benjamin,

    da mein English nicht so gut ist, Frage ich einfach mal nach.

    Kann man mit dieser Methode beim laden eines flv files außerhalb des Puffers springen ?? Ich benutze lighttpd. Mit dem JW Flashplayer funktioniert das Wunderbar. Nur in Flex bekomme ich das nicht am laufen. Hast du eine Idee für mich ?

  7. Benjamin (Admin) on December 11th, 2007 1:40 am

    @Chrisz: Dieser Post hat nichts mit deinem Problem zu tun. lighthttp funktioniert natürlich auch mit flex aber dafür müsstest du einen eigenen Player schreiben. Du solltest dir unbedingt auch mal Red5 anschauen. Damit kannst du dann echtes streaming machen und es ist umsonst.

  8. Erik on December 11th, 2007 7:03 pm

    @Jason, @Benjamin: According to the Flex 3 API docs:

    “In the Adobe® Integrated Runtime, content in the application security sandbox (such as content installed with the AIR application) can use any request headers, without error. However, for content running in the Adobe Integrated Runtime that is in a different security sandbox, or for content running in Flash® Player, using following request headers cause a runtime error to be thrown, and the restricted terms are not case-sensitive (for example, Get, get, and GET are each not allowed):

    Accept-Charset, Accept-Encoding, Accept-Ranges, Age, Allow, Allowed, Connection, Content-Length, Content-Location, Content-Range, Date, Delete, ETag, Expect, Get, Host, Keep-Alive, Last-Modified, Location, Max-Forwards, Options, Post, Proxy-Authenticate, Proxy-Authorization, Public, Put, Range, Referer, Retry-After, Server, TE, Trace, Trailer, Transfer-Encoding, Upgrade, URI, User-Agent, Vary, Via, Warning, WWW-Authenticate, x-flash-version.”

  9. William from Lagos on March 23rd, 2008 6:04 pm

    Could you please provide any form of sample source files showing how this (resuming downloads) can be done

  10. deus.ex on April 15th, 2008 4:27 pm

    As i can see the logic is following
    //——————————
    //start download
    var request:URLRequest = new URLRequest(downLoadURL);
    var urlStream:URLStream = new URLStream();
    urlStream.load(request);
    …………..
    //pause?
    urlStream.close();
    ……..
    //resume your code
    var header1:URLRequestHeader = new URLRequestHeader(”range”,”bytes=”+currentBytesPosition+”-”+toRange);
    var re:URLRequest = new URLRequest(downLoadURL);
    re.requestHeaders.push(header1);
    currentBytesPosition = toRange;
    urlStream.load(re);
    //——————————-

    if I’m right – resumed download urlStream will have only part of data (from “currentBytesPosition” to “toRange”) but previously loaded data will be lost.
    Please let me know if I’m doing something wrong.
    Thanx.

  11. Benjamin (Admin) on April 16th, 2008 1:11 am

    Yeah that`s correct but with AIR you can save the bytes locally and put them together again…

  12. deus.ex on April 16th, 2008 10:17 am

    Thanx! Don’t know why but I didn’t think about storing parts of downloaded data on one ByteArray:). Thanx again

  13. Freddy on June 9th, 2009 10:18 am

    There is a very high chance I will be using this to pause/resume downloads.

    Being able to “pause” downloads is also a way to get around ongoing downloads blocking the connections for an in app browser. Any alternate tip to achieve that? :)

  14. Mariush T. – Freelance Flex/PureMVC Developer – blog » Blog Archive » Resumable File Downloader – Simple AIR app on March 11th, 2010 12:59 am

    [...] flv, etc) and save to the user’s computer. Big Thanks to Benjamin Dobler for his blog post Resumable Downloads with AIR. Tags: AIR, ByteArray, FileStream, Flex 4, URLRequest, URLRequestHeader, [...]

  15. Mariush T. on March 11th, 2010 1:17 am

    Great tutorial!
    I just made a live demo of Resumable File Downloader(AIR app with source code).

Leave a Reply