James Gardner: Home > Blog > 2007 > Multiple File Uploads with...

Multiple File Uploads with Progress Meters using Flash 8 and JavaScript

Posted:2007-09-25 15:57
Tags:Pylons, Python, Web, Flash

There are two problems with uploading files over the web using a simple HTML Form

There are ways of solving these problems using AJAX and a hidden iframe (I might write one up if I get a chance) but Flash 8 provides a better solution because it allows you to select multiple files from a single dialog box so that if you want to upload a hole directory you don't have to select each of the files individually. Flash 8 can also keep track of the upload progress on the client side so you don't need to implement any server-side feedback system as the file is being uploaded. You can also specify a maximum file size.

There are a number of open source implementations which expose this Flash 8 functionality via JavaScript. The one I use is SWFUpload.

If you follow on from my last upload example you can replace the index() action with this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Upload files using flash and javascript - SWFUpload</title>
    <script type="text/javascript" src="jscripts/SWFUpload/SWFUpload.js"></script>
    <script type="text/javascript" src="jscripts/example_callbacks.js"></script>
    <script type="text/javascript">
            var swfu;
            var swfu2;
            window.onload = function() {
                    // Max settings
                    swfu = new SWFUpload({
                            upload_script : "/up/upload",
                            target : "SWFUploadTarget",
                            flash_path : "jscripts/SWFUpload/SWFUpload.swf",
                            allowed_filesize : 3072000,     // 3000 MB
                            allowed_filetypes : "*.*",
                            allowed_filetypes_description : "All files...",
                            browse_link_innerhtml : "Browse",
                            upload_link_innerhtml : "Upload queue",
                            browse_link_class : "swfuploadbtn browsebtn",
                            upload_link_class : "swfuploadbtn uploadbtn",
                            flash_loaded_callback : 'swfu.flashLoaded',
                            upload_file_queued_callback : "fileQueued",
                            upload_file_start_callback : 'uploadFileStart',
                            upload_progress_callback : 'uploadProgress',
                            upload_file_complete_callback : 'uploadFileComplete',
                            upload_file_cancel_callback : 'uploadFileCancelled',
                            upload_queue_complete_callback : 'uploadQueueComplete',
                            upload_error_callback : 'uploadError',
                            upload_cancel_callback : 'uploadCancel',
                            auto_upload : false
                    });
            }
    </script>
    <style type="text/css">
            .swfuploadbtn {
                    display: block;
                    width: 100px;
                    padding: 0 0 0 20px;
            }
            .browsebtn { background: url(/images/add.png) no-repeat 0 4px; }
            .uploadbtn {
                    display: none;
                    background: url(/images/accept.png) no-repeat 0 4px;
            }
            .cancelbtn {
                    display: block;
                    width: 16px;
                    height: 16px;
                    float: right;
                    background: url(/images/cancel.png) no-repeat;
            }
            #cancelqueuebtn {
                    display: block;
                    display: none;
                    background: url(/images/cancel.png) no-repeat 0 4px;
                    margin: 10px 0;
            }
            #SWFUploadFileListingFiles ul {
                    margin: 0;
                    padding: 0;
                    list-style: none;
            }
            .SWFUploadFileItem {
                    display: block;
                    width: 230px;
                    height: 70px;
                    float: left;
                    background: #eaefea;
                    margin: 0 10px 10px 0;
                    padding: 5px;

            }
            .fileUploading { background: #fee727; }
            .uploadCompleted { background: #d2fa7c; }
            .uploadCancelled { background: #f77c7c; }
            .uploadCompleted .cancelbtn, .uploadCancelled .cancelbtn {
                    display: none;
            }
            span.progressBar {
                    width: 200px;
                    display: block;
                    font-size: 10px;
                    height: 4px;
                    margin-top: 2px;
                    margin-bottom: 10px;
                    background-color: #CCC;
            }
    </style>
</head>
<body>
    <h1><span>SWFUpload Testpage</span></h1>
            <h2>Upload Example</h2>
            <p>Replace contents of a div with links for uploading and browsing,
            degrades gracefully if flash/javascript isn't accessible</p>
            <div id="SWFUploadTarget">
                    <form action="upload.php" method="post" enctype="multipart/form-data">

                            <input type="file" name="Filedata" id="Filedata" />
                            <input type="submit" value="upload test" />
                    </form>
            </div>
            <h4 id="queueinfo">Queue is empty</h4>
            <div id="SWFUploadFileListingFiles"></div>
            <br class="clr" />
            <a class="swfuploadbtn" id="cancelqueuebtn"
            href="javascript:cancelQueue();">Cancel queue</a>
</body>
</html>

You'll also need to download the SWFUpload source distribution and copy the jscripts directory into your Pylons project public directory so that the /jscripts/ links in the HTML work correctly. The example also uses some images which are attached to this entry and should be put in the public/images directory so that the /images/ URLs resolve.

Accept icon Add icon Cancel icon Progress bar

If you have Flash 8 or above and run this example you'll now be able to upload multiple files to the unmodified controller. You can change the CSS and the images to change how the upload behaves and there are plenty of hooks for you to tie what's happening in Flash to your page's JavaScript.

Sample Pylons File Upload Project

(view source)

James Gardner: Home > Blog > 2007 > Multiple File Uploads with...