File Uploader

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
Loading ... Loading ...

Have you ever wanted to write a Flash file uploader that allows your clients, or users, to upload (or download) files to and from your website? The FileReference class (for Flash 8 or later) allows you to do this.  Although not documented in our help files, a detailed description of the FileReference class can be found at the Adobe website or in the Flash AS2 language reference pdf document which can be downloaded from here.

In addition to authoring your Flash page, you will also need to create the appropriate server pages to support the file uploads. An example of a php server page is given at the end of this article.

The example swf file below allows you to initiate the download of some different items from our server. The transfer status messages received by the FileReference object are shown in the status window.

The sequence of events is slightly different for uploads and downloads. In the examples below, G_fr is the name of the file reference object that is defined as shown below:

var G_fr = new flash.net.FileReference(); // new file reference object

Downloads

Initiate the download using

G_fr.download(url);

url is the URL of the file that is to be downloaded. This method will invoke a file browse dialog that allows the user to select (or cancel) the location for the download file.

A return value of true indicates that the download has successfully commenced.

Uploads

Initiate the upload using:

G_fr.browse(typelist);// select file to be uploaded

// after checking that selected file is valid for upload call
G_fr.upload(url);// commence the upload

The browse command opens a file selection dialog that allows the user to select the file to be uploaded. The upload command starts the upload.

typelist is an array that defines the type of files that are browsed for. See the previously mentioned AS2.0 script reference for more information.  As an example, to browse for jpg images use:

[{description: "Images", extension: "*.jpg"}]

url is the name of the URL that handles the upload. This is generally a php or an asp server page. See below for an example php page.

Monitoring

Once the transfer has commenced, the FileFeference object sends feedback using a number of defined events that can be accessed using a listener object:

onCancel Called if the cancel button of the file browse dialog is pressed.
onComplete Called when the transfer has competed successfully
onHTTPError Called when an upload fails because of a HTTP error.
onIOError
Called when transfer fails due to some IO error. For downloads this could also correspond to an HTTP error.
onOpen Called when the transfer process has started.
onProgress Called multiple times during the transfer. Indicates the number of bytes transferred and the number of bytes total.
onSecurityError Called when transfer fails because of a security issue. Most likely cause is cross domain references.
onSelect Called when file browse dialog has selected a file.
onUploadCompleteData Called after data is received from the server after a successful upload. The processing that occurs here depends on the data returned from the upload URL. The server upload page could be authored to return specific data about the success or failure of the upload.

Event handling is achieved through the use of a listener object that is then associated with the FileReference Object.

For example, to monitor onProgress events:

var listener:Object = new Object(); // create a listener object
listner.onProgress = function(fileRef:FileReference, bytesLoaded:Number, bytesTotal:Number):void {
  trace(bytesLoaded add "/" add bytesTotal);
}
G_fr.addListener(listener); // associate the listener with the file reference object.

In the above example, a trace statement will be called for each invocation of the onProgress event. The onProgress event would normally be used to provide % complete feedback.

The exact parameters used by each of the event functions is defined in the AS 2.0 reference guide mentioned above.

Examples

Downloads

The .swi file for the above example can be downloaded here.

Analysis

To simplify configuration, the values shown in the list box as well as the associated download URLs have been defined as parameters (List Values and URLs) associated with the download object.

The Script for the movie is shown below:

function StartDownload(selection) {
    // the download urls are stored in a line separated list in parameters.URLs
    var s = parameters.URLs.split(chr(13));    // split into individual URLs
    if (selection < 1 || selection > (s.length)) {
        statusText.SetText("Download URL not defined" add newline);
        return;
    }

    // download the selected URL. 1 corresponds to the 1st URL
    if (!G_fr.download(s[selection-1])) {
        statusText.SetText("Failed to open: " add s[selection-1]);
    } else {
        DownloadObjectsVisible(true);
        progressbar.SetValue(0);
        statusText.SetText("");
    }
}
function DownloadObjectsVisible(m) {
    // sets / resets the visibility of the download specific objects
    progressbar._visible = m;
    Button_Cancel._visible = m;
}
function Events(n,v) {
    switch(n) {
    case "Button_Cancel":
        G_fr.cancel();    // cancel the download
        // show cancelled in status area.
        statusText.AppendText("User Cancelled download" add newline);
        DownloadObjectsVisible(false);
        break;

    case "Combo_silver":
    case "Button_Download":
        StartDownload(Combo_silver.GetCurSel());
        break;
    }
}

onSelfEvent(load) {
    var G_fr = new flash.net.FileReference();
    var listener:Object = new Object();
    listener.onSelect = function(f:FileReference):Void {
        statusText.SetText("Downloading: " add f.name add newline);
    }
    listener.onCancel = function(f:FileReference):Void {
        // user pressed cancel on file browse dialog
        statusText.AppendText("User Cancelled" add newline);
        DownloadObjectsVisible(false);
    }
    listener.onOpen = function(file:FileReference):Void {
        statusText.AppendText("onOpen: " + file.name + newline);
    }
    listener.onProgress = function(file:FileReference, bytesLoaded:Number, bytesTotal:Number):Void {
        statusText.AppendText("onProgress: bytesLoaded " + bytesLoaded + " / " + bytesTotal + newline);
        progressbar.SetValue(bytesLoaded/bytesTotal * 100);
    }
    listener.onComplete = function(file:FileReference):Void {
        statusText.AppendText("onComplete: Download of [" add file.name add "] complete." add newline);
        DownloadObjectsVisible(false);
    }
    listener.onHTTPError = function(file:FileReference, error):Void {
        statusText.AppendText("onHTTPError: " + file.name + "E:" add error + newline);
        DownloadObjectsVisible(false);
    }
    listener.onIOError = function(file:FileReference):Void {
        statusText.AppendText("onIOError: " + file.name + newline);
        DownloadObjectsVisible(false);
    }
    listener.onSecurityError = function(file:FileReference, errorString:String):Void {
        statusText.AppendText("onSecurityError: " + file.name + " errorString: " + errorString + newline);
        DownloadObjectsVisible(false);
    }
    G_fr.addListener(listener);
    DownloadObjectsVisible(false);
}

The functions have the following purpose:

StartDownload: This function is passed the index of the selected item in the combo box. It looks up the associated URL from the parameter URL and then initiates the download using G_fr.download(). If the download is started successfully it initializes the progress bar and the status text area and makes the progress bar and cancel button visible.

DownloadObjectsVisible(): This function sets (or resets) the visibility of the progress bar and cancel button.

Events(): This function handles events from the Cancel and Download buttons and also the combo box. The Cancel button cancels the download via G_fr.cancel(). The Download button an combo events cause the download to commence by calling the StartDownload() function described above.

onSelfEvent (load): This function creates the file reference object (G_fr) and defines the various event actions that are assigned to the listener object (listener).

Uploads

The image below shows the example upload movie. The movie allows the user to browse for and upload a jpeg image file. The upload file size is limited to 60kBytes. The movie allows the user to optionally enter additional information about the image such as title and description. The status area shows the progress of the upload.

The example files (.swi file and .php file) can be downloaded from here.

Analysis

To simplify configuration, the upload URL has been defined as a parameter for the editupload movie clip. You will need to set this parameter to the appropriate URL before using the sample file.

The script used in the .swi file is shown below:

function Events(n,v) {
    if ("Button_Browse" == n) {
        G_fr.browse([{description: "Images", extension: "*.jpg"}]);
    } else if ("Button_Upload" == n) {
        // start the upload
        G_fr.postData = "desc=" add bodyText.t1.text add "&title=" add title.text;
        if (!G_fr.upload(parameters.UploadURL)) {
            status.SetText("Upload dialog failed to open.");
        } else {
            progressbar._visible = true;
            progressbar.SetValue(0);
            status.SetText("");    // clear any previous status info
        }
    }
}

onSelfEvent(load) {
    var G_fr = new flash.net.FileReference();
    var listener:Object = new Object();
    listener.onSelect = function(f:FileReference):Void {
        uploadfile.text = f.name;
    }
    listener.onCancel = function(f:FileReference):Void {
        uploadfile.text = "";
        trace("User Cancelled");
    }
    listener.onOpen = function(file:FileReference):Void {
        status.AppendText("onOpen: " + file.name + newline);
    }
    listener.onProgress = function(file:FileReference, bytesLoaded:Number, bytesTotal:Number):Void {
        status.AppendText("onProgress with bytesLoaded: " + bytesLoaded + " / " + bytesTotal + newline);
        progressbar.SetValue(bytesLoaded/bytesTotal * 100);
    }
    listener.onComplete = function(file:FileReference):Void {
        status.AppendText("onComplete: " + file.name + newline);
        progressbar._visible = false;
    }
    listener.onHTTPError = function(file:FileReference, error):Void {
        status.AppendText("onHTTPError: " + file.name + "E:" add error + newline);
        progressbar._visible = false;
        status._visible = true;
    }
    listener.onIOError = function(file:FileReference):Void {
        status.AppendText("onIOError: " + file.name + newline);
        status._visible = true;
    }
    listener.onSecurityError = function(file:FileReference, errorString:String):Void {
        status.AppendText("onSecurityError: " + file.name + " errorString: " + errorString + newline);
        status._visible = true;
    }
    listener.onUploadCompleteData = function(file:FileReference, data:String):Void {
        status.AppendText(data add newline);    // show the result code
    }
    G_fr.addListener(listener);
    progressbar._visible = false;
}

The Events() function handles the Browse and Upload buttons. On a Browse event, the browse window is invoked by the line:

G_fr.browse([{description: "Images", extension: "*.jpg"}]);

This specific configuration allows browsing specifically for jpg images.

When the Upload button is pressed, the title and description are sent using the postData property:

G_fr.postData = "desc=" add bodyText.t1.text add "&title=" add title.text;

This causes the data to be sent using the post variables desc and title. These can be accessed in the remote php script via $_POST["desc"] and $_POST["title"]. The upload is then initiated using the parameter that is defined for the upload URL.

G_fr.upload(parameters.UploadURL);

The onSelfEvent(load) function creates the file reference object (G_fr) and defines the various event actions that are assigned to the listener object (listener). Take specific note of the onUploadCompleteData event handler which displays the returned text from the php page in the status area.

To use the upload example you will need to create an upload script file on your website. An example php file is shown below (and also included in the sample zip file):

<?php
if (is_uploaded_file($_FILES['Filedata']['tmp_name']) && ($_FILES['Filedata']['size'] < 60000)){
    // warning, copying uploaded files to your web folder, may enable an attacker to compromise the
    // security of your website.
    // use this example entirely at your own risk.
    // no responsibility will be accepted for any use or misuse of this example file.

    // check the uploaded file type is jpeg
    if ("image/jpeg" != mime_content_type($_FILES['Filedata']['tmp_name'])) {
        // we only allow jpg
        echo "Error: filetype not allowed";
    } else {
        // file is allowed file type and is within allowed size. 

        // leave it with the assigned temporary name and move to the upload folder.
        // in this way a potential attacker should not be able to overwrite existing web files.
    	$uploadDirectory="upload/";
        // the temporary name is something like /tmp/phpXXXXXX where XXXXXX is a random string
    	// substr is used to remove the leading php from the name.
	    $tmpbasename = substr(basename($_FILES['Filedata']['tmp_name']),3);
    	$uploadFile=$uploadDirectory.$tmpbasename.".jpg"; // force jpg extension. 

    	// now copy the uploaded file to the web area.
    	// only do this if you are 100% sure the file does not constitute a security risk.
	    copy($_FILES['Filedata']['tmp_name'], $uploadFile);

	    // note that
	    // $_POST["title"] contains the user entered title and
    	// $_POST["desc"] contains the user entered description
    	// these post variables were defined using G_fr.postData in the swf file.
    	// these items could be added to database entry for the uploaded file if desired.

	    echo "OK: " . $uploadFile;
	}
 } else {
  // file too large or possibly dangerous file.
    echo "Error: file too large";
 }
?>

In this example, only jpg images are allowed and their size must be less than 60000 bytes. If the uploaded file meets these conditions, the php file transfers the uploaded file to an upload folder.

The upload folder is a sub folder of the folder containing the php file. Create the upload folder if it does not already exist.

Note that within the PHP script, references to the uploaded file are via $_FILES['Filedata']. The name ‘Filedata‘ is set by the FileReference object.

On completion of the upload the path to the renamed file is displayed.

I recommend that you refer to the detailed php manual pages for tips on security, more detailed information and other suggestions. Some commonly requested changes are described below.

Changing Upload Limit

It is necessary to alter the file size test in the php file. For example if you wish to allow 50Mbyte uploads, change the line:

if (is_uploaded_file($_FILES['Filedata']['tmp_name']) && ($_FILES['Filedata']['size'] < 60000)){

to

if (is_uploaded_file($_FILES['Filedata']['tmp_name']) && ($_FILES['Filedata']['size'] < 50000000)){

It is possible to add a check of the opened file size before the upload commences in the swi / swf file. This has the advantage of warning the user that the file is too large before the upload commences. The size check in the php file should still be retained as this check is easily circumvented.

The modified script for the .swi Events function is shown below:

    ...
    } else if ("Button_Upload" == n) {
        // check that file is below limit
        if (G_fr.size > 50000000) { // 50Mbyte limit
            status.SetText("File too large");
            return;
        }
        // start the upload
        G_fr.postData = "desc=" add bodyText.t1.text add "&title=" add title.text;
       ...

If you have added such a check, you must also modify this file size to match the file size check in the php file.

Modifying the File Type

Modify the file type that is browsed for in the swi / swf file. This is done by modifying the parameters to the browse function call. The examples below assume a change to the file type of pdf.

To browse for .pdf files, change the line:

if ("Button_Browse" == n) {
        G_fr.browse([{description: "Images", extension: "*.jpg"}]);

To

if ("Button_Browse" == n) {
        G_fr.browse([{description: "Adobe pdf", extension: "*.pdf"}]);

The upload php file will also require modification:

  • The type checking (if used) will require modification, however I am not sure if pdf files are recognised by the type checking functions, so it may be necessary to simply remove the check.
  • The copy action will require modification to add the file correct extension. Modify the line:
$uploadFile=$uploadDirectory.$tmpbasename.".jpg"; // force jpg extension.

To

$uploadFile=$uploadDirectory.$tmpbasename.".pdf"; // force pdf extension.

in the php upload file.

 

Tags: , , , , ,

36 Responses to “File Uploader”

  1. I’ve tried this and all I get is error string: SecuritySandboxError, any ideas what I am doing wrong?

  2. Sorry, me again. Got around this but I’m getting an http error, how exactly do I tell the swi file my website directory?

    • jonh says:

      Hi,
      Are you uploading or downloading? What is the http error number?
      For downloads the URLs are set using the URL parameter of the download object. Each download file is specified on a new line.
      For uploads the upload URL is set using the “Upload URL” parameter of the upload object.
      For uploads you will need to modify and upload the sample php file to your website and quote the URL to that page in the upload URL parameter mentioned above. The folder where the uploaded files are stored is defined within the php file.

      • Hi, I’m uploading, or trying to. The error code seems to be 405.

        I’ve tried adjusting the files but I don’t think I’ve done it right. My site is

        http://www.phantasy-media.co.uk

        The code I have is;

        G_fr.postData = “desc=” add bodyText.t1.text add “&title=” add title.text;
        if (!G_fr.upload(parameters.www.phantasy-media.co.uk/upload)) {
        status.SetText(“Upload dialog failed to open.”);

        As for the PHP file, do I leave it called uploaddemo? and I can’t see where I alter that for my site if at all?

        Thanks for your help

        Kev

        • jonh says:

          Hi,

          It sounds like the POST method has been disallowed on your server.
          See http://www.checkupdown.com/status/E405.html

          Jon

          • My server does allow post as I have an enquiry form on there that uses the post command to send variables to a php file.

            If I take the /upload off the above script I get 404 HTTP error.

            ???

            Kev

          • jonh says:

            Hi,

            Modify your code to be
            if (!G_fr.upload(“http://mydomain.com/uploadpage.php”)) …
            or return the statemt to be the same as in the sample file and enter the full URL of your php upload page into the URL parameter via the parameers panel (ie do not edit the script).
            Note that in the above example the http statement should represent the full path to your modified php upload file.

  3. http://www.phantasy-media.co.uk/Upload%20Test.html

    This is the link to my test bit, I’m now getting a really weird fatal error, can you try this link and see the error you get and help.

    Is it the php that needs altering?

    Sorry about this, I think we are getting closer

    Kev

    • jonh says:

      Hi,
      Yes, you need to alter the php.
      It appears that the function mime_content_type() is not supported by your version of php.

      Change the following lines in the php file:
      // check the uploaded file type is jpeg
      if (“image/jpeg” != mime_content_type($_FILES['Filedata']['tmp_name'])) {
      // we only allow jpg
      echo “Error: filetype not allowed”;

      to

      // check the uploaded file type is jpeg
      $finfo = finfo_open(FILEINFO_MIME_TYPE);
      if (“image/jpeg” != echo finfo_file($finfo, $_FILES['Filedata']['tmp_name'])) {
      // we only allow jpg
      echo “Error: filetype not allowed”;

  4. Sorry about this getting a syntax error now, if you try the link you’ll see what it is.

    I have altered the php to the below;

    <?php
    if (is_uploaded_file($_FILES['Filedata']['tmp_name']) && ($_FILES['Filedata']['size']

    • jonh says:

      The line you have quoted appears to be incomplete.
      It should be something like:
      if (is_uploaded_file($_FILES['Filedata']['tmp_name']) && ($_FILES['Filedata']['size'] < 60000)){

      • Sorry it seems to have not sent you all the file, it’s an error in the new code you sent me above line 11, if you try my link again you will see

        Thanks

        Kev

  5. // check the uploaded file type is jpeg
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    if (“image/jpeg” != echo finfo_file($finfo, $_FILES['Filedata']['tmp_name'])) {
    // we only allow jpg
    echo “Error: filetype not allowed”;

    It’s this new bit that seems to be causing a syntax error

    Thanks

    Kev

    • jonh says:

      opps, sorry a stupid typo on my part. It should be finfo_file(… not echo finfo_file(…

      Please checkout this website
      http://php.net/manual/en/index.php

      For any other issues relating to php.

      I tried on my system and finfo_open does not seem to be supported so you may have to experiment with other php commands (see the above website). Alternatively remove the test.

      Jon

  6. I have taken the check out completely and the file now works, thanks for all your help.

    Just one more thing, I want to adapt the file to accept PDF files not JPEG and they need to be up to 50mb in size, is this possible?

    Thanks

    • jonh says:

      Hi,

      The flash player officially supports uploads and downloads up to 100Mbyte. However it is possible that other external issues may limit the upload file size.

      I have modified the blog article to show how to tailor for specific file types and upload limits. – See the end of the article.

      Jon

      • Hi Jon,

        I’ve managed to do that and it now accepts PDF files, but despite changing the file size limit to the 50mb value it won’t even upload a 2mb file, it shows the ‘file to large’ error in the status box.

        Sorry to give you so much grief, do you have any ideas what might be causing this?

        Kev

        • jonh says:

          Hi,
          try changing the echo statement at the bottom of your php file to:
          echo “Error: file too large:”.$_FILES['Filedata']['size'];

          That way you will see how large the reported file size is.
          If the number reported is less than 50000000 then double check the 1st line and the number of zeros.

          Jon

  7. Where do I find the php.ini file to see what the max is set to?

    • jonh says:

      Hi,

      I am sorry, I am not an expert in php and I am unable to answer that question. I suspect the file location depends on the type of http server that you are running and exactly what type of php you are using. Please see the person that has setup your server or contact their support staff.

      If you have super user access to a command window I think something like:
      find / -name php.ini -print
      will list all files called php, but again the command sytax may not be exactly correct.

      You could also try googling php.ini.

      Jon

  8. I have spoke to my ISP and they are changing the upload limit for me, it is the php.ini file that is the problem. Thanks for your help.

    Kev

  9. Hi Jon, sorry one more question. The script is working great on files up to about 12mb. We changed the php.ini to say 50mb for both the maximum file upload and the maximum data a POST func can write.

    Over 12mb I get a HTTP error 500, any suggestions? my ISP guys are lost now.

    Thanks

    Kev

  10. Hi Jon, I am now trying to set up the download. I have this working perfectly offline, but when I upload it to my site I get a security sandbox error. I am trying to let people download content from my own site, not across domains.

    Any suggestions?

    Kev

  11. jonh says:

    Hi Kevin,

    Sorry about delayed reply. I was away on holidays.

    I am not sure why you get the sandbox error. I setup a test site with a number of pdf files and was able to select and download them without any problems.

    Can you ask your web support staff if a cross domain policy file has been setup. This file has the name crossdomain.xml

    In the absence of such a file, downloads from the same domain should work ok. However it is possible to setup a cross domain policy file that would prevent downloads from the same domain.

    If a policy file has been setup, please have your web staff review this page:
    http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html

    Jon


Switch to our mobile site