Avg. Rating 4.0

Problem

I have a AIR application using the HTML component to display a simple HTML page. In this page, I only have a link to a PHP script forcing the download of a PDF file. The problem is AIR doesn't know what to do with pages forcing files download, if you click on it in your AIR application, nothing will happen.

Solution

Each time the HTML component renders HTML, I will fetch every links included in the page and bind the "click" event to an Actionscript Method. In this method, I'll open a save window using the File class and download the file targeted by the link.

Detailed explanation

I have a simple PHP file "get.php" forcing the download of a PDF file :

<?php $fileName = dirname(__FILE__).'/phpentreprise.pdf'; 
if(file_exists($fileName)) {
header('content-disposition: attachment; filename='.basename($fileName));
header('content-type: application/force-download');
header('content-length: '.filesize($fileName));
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('pragma: no-cache');
header('expires:0');
readfile($fileName);
exit(); }


In my AIR application, I have a HTML component which location is a page containing a link to that downloading page.
There also is a progress bar visible when a file is being downloaded, showing the progress of the download.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication  xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical"
    verticalAlign="top"
    horizontalAlign="center"
    creationComplete="init(event)">
<mx:Script source="com/palleas/fetchLinks.as" />
<mx:HTML id="browser" location="http://labo.palleas.com/PHP/force-download/index.php" width="100%" height="50%" />
<mx:states>
  <mx:State name="downloading">
   <mx:AddChild>
    <mx:ProgressBar id="dlPGBar" mode="event" label="Downloading file" labelPlacement="center" />
   </mx:AddChild>
  </mx:State>
</mx:states>
</mx:WindowedApplication>

If I click on that link, nothing should happen unless I bind an Actionscript method to the javascript click event, on every link.

import flash.events.Event;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;

import mx.controls.Alert;

protected var loader:URLLoader;
protected var request:URLRequest;
protected var saver:File;

// called when the application is ready
protected function init(e:Event):void {
    browser.addEventListener(Event.HTML_RENDER,onRender)
}

// called when the html component has rendered HTML code
protected function onRender(e:Event):void {
    var links:Object =  HTML(e.target).htmlLoader.window.document.links;
    for(var i:int=0;i<links.length;i++) {
        links[i].onclick = clickhandler;
    }
}

// called when the user clicks on a HTML link
protected function clickhandler(e:Object):Boolean {
    // the download will be started only if a file
    // is not currently being downloaded
    if(null == saver) {
        var url:String = e.currentTarget.toString();
        loader = new URLLoader();
        loader.dataFormat = URLLoaderDataFormat.BINARY;
        loader.addEventListener(Event.COMPLETE,onComplete);
        request = new URLRequest(url);
        request.followRedirects = true;
        saver = new File();
        saver.browseForSave("Save the file");
        saver.addEventListener(Event.SELECT,onSave);
    } else {
        Alert.show("Please wait the first is completely downloaded");       
    }
    return false;
}

// called when the user has chosen a file to download the file to
protected function onSave(e:Event):void {
    currentState = "downloading";
    dlPGBar.source = loader;
    loader.load(request);
}

// called when the download is complete
protected function onComplete(e:Event):void {
    var stream:FileStream = new FileStream();
    stream.open(saver,FileMode.WRITE);
    stream.writeBytes(loader.data);
    stream.close();
   
    currentState = "";
    saver = null;
    request = null;
    loader = null;
   
    Alert.show("File successfully downloaded !");
}

FetchLinks.zip
[FlexBuilder 3 project archive]
fetchlinks.jpg
Report abuse

Related recipes