Tutorial: Cross browser Multiple Uploader With SWFUpload And JavaScript

Most of us will know that performing multiple upload with JavaScript alone that are both dynamic and powerful is complicated and confusing. Let alone having cross browser capability. Furthermore, all browsers will only allow one file to be chosen per dialog box at any one time. This makes multiple upload a tedious job for our users. Moreover, most methods are having a hard time populating the bytes uploaded to the system (progress bar). Therefore, there is a need for a more powerful and easier solution for multiple uploader that can both upload asynchronously and allows users to select multiple files at one go.

Solution

We can use JavaScript, iFrame and PHP library to perform the above task. However, this is more complicated and required to configure the server so that it contains the PHP library. If you are working on Open Source application, requesting users to configure their PHP server in order to use a certain function is not desirable. However, this can be done as follow

  • Using JavaScript to eliminate the need for multiple upload file
  • Using iFrame to store each upload bar to be prepared to upload
  • PHP itself is capable to receive multiple files
  • However, PHP is unable to show the process bar of each upload. This will required < a href="http://pecl.php.net/package/APC" rel="nofollow">Perl library(php_apc.dll) that was built for PHP which is currently unavailable in PHP 5.2 but will be placed into PHP in version 6. (that's is why i didn't write this tutorial)

I personally did the above 2 years ago when i was still working for an Australia based company (which i might write it out in this site later). The other method is to use a flash uploader such as SWFUpload.

What is SWFUpload?

SWFUpload is an open source flash uploader that WordPress is currently using. Although this is not a normal plug and play flash uploader, it is certainly updated and powerful. Moreover, it has cross browser capability and allow users to select multiple files at one time. However, implementing it and understanding it do takes time. But it worth it.

Let's get started

I did this on one of my WordPress plugin. But getting it to work really waste a lot of my time. Therefore, i decided to write them up for some of you out there who are just getting started with this. Enough of chit-chat. Let's get started. The fastest and easiest way is to download their sample files. The sample files will have most of the things you need. The sample files are similar to their demo page. This means that the sample files are the exact same thing as the demo given. Let's just start with the simplest first. Look at Simple Upload Demo and this is what we want to achieve at the end of this article. What you need are the following files in the simpledemo folder that you have downloaded to your local drive.

  • index.php
  • all files in js folder
  • all files in css folder
  • all files in swfupload folder located outside of simpledemo folder

Just in case you don't get it, here's a screenshot.
simpledemo
basically you will only need partial code from index.php which you can figure out them very quickly. The files that you would actually edit are the codes in index.php and handler.js only.

Important Part

Basically, if you throw the sampledemo into your server it should display exactly the same as what you see on their demo page. However, i do not think you want it to be exactly the same. You can try to read the documentation which is quite helpful in some way and in many way it does not. Unlike normal upload, SWFUpload work a little bit different which you will need to know(or suffer).

  • SWFUpload do not use MIME type, so don't try to validate whether it is image in PHP. This is a flash uploader!
  • SWFUpload will required the initialization of the object to work. Invalid of initialization will cause you a headache in just displaying the upload button (quite easy just don't be careless)
  • You need to ensure that your PHP files on the server side is working correctly before using SWFUpload. This means that you must check whether it is uploading correctly using normal file uploader
  • The above part will help u a bit in reducing debugging problem later. The other problem you might face greatly is debugging issues. How do we debug when we are using flash uploader? You will have to look up at the handler.js file with the method 'uploadSuccess' that will return you with the serverData. This 'serverData' variable contains what is happening on your server side. This is the only thing that can assist you in debugging
  • you can write methods to overwrite the handler default in the swfuploader.js by using the handler.js. No modification is needed in swfuploader.js.

The list can just go on, if you face any problem you can just send me an email. For the important initialization part,

		var swfu;

		window.onload = function() {
			var settings = {
				flash_url : "../swfupload/swfupload.swf",//the path of swfupload.swf.eg. http://hungred.com/swfupload.swf
				upload_url: "upload.php",//the path of your upload php file. eg. http://hungred.com/upload.php
				post_params: {"PHPSESSID" : "<?php echo session_id(); ?>"}, // this is additional information for your upload.php file. eg. in upload.php 'echo $_POST['PHPSESSID'];'
				file_size_limit : "100 MB", //the limit impose for your flash uploader which is different from the one in your upload.php (additional validation)
				file_types : "*.*", // allowed file type. eg. '*gif*png*jpg';
				file_types_description : "All Files", //the name of the dialog box
				file_upload_limit : 100,//the number of upload allowed. eg. max is 100 
				file_queue_limit : 0,// the maximum amount of queue upload allowed. eg. 0= unlimited
				custom_settings : {
					progressTarget : "fsUploadProgress",
					cancelButtonId : "btnCancel"
				},
				debug: false,//debugging mode that display all the information of the flash uploader. You can customize them in handler.js

				// Button settings
				button_image_url: "images/TestImageNoText_65x29.png",//button image populated by the flash uploader
				button_width: "65", //width of the button
				button_height: "29",//height of the button
				button_placeholder_id: "spanButtonPlaceHolder", //the id container of the button. eg. <div id="spanButtonPlaceHolder"></div>
				button_text: '<span class="theFont">Hello</span>',//the text in the button
				button_text_style: ".theFont { font-size: 16; }",//the style of the text
				button_text_left_padding: 12,//left padding
				button_text_top_padding: 3,//top padding
				
				// The event handler functions are defined in handlers.js
				file_queued_handler : fileQueued,
				file_queue_error_handler : fileQueueError,
				file_dialog_complete_handler : fileDialogComplete,
				upload_start_handler : uploadStart,
				upload_progress_handler : uploadProgress,
				upload_error_handler : uploadError,
				upload_success_handler : uploadSuccess,
				upload_complete_handler : uploadComplete,
				queue_complete_handler : queueComplete	// Queue plugin event
			};

			swfu = new SWFUpload(settings);
	     };

The code above are so long but there are no comment on it when you look at the demo files provided. I have comment above to explain what it does since it is criteria important you understand them during your development. Handler do not have comment as those are methods exist in handler.js which means you can change how it should be handler. Lastly, you can edit the display by changing their css file, default.css. If you need additional example, please look into your WordPress swfupload folder located in the wp-include folder.

The Demo

I can't really provide with you with the exact same demo given by SWFUpload. You can see the more advance part on WordPress, 'Add new' post section. Or you can view the screen shot that i did with my plugin below.
demo

The Summary

The reason for this article is to make aware some of the points in SWFUpload flash uploader. Although it is powerful, the community for such application is still quite small which might bring some difficulty for some of the people out there who are starting to use this application. Why this and not other alternative uploader? Updated, maintained, acknowledged, no additional configuration required, multiple selection, cross browser, small size, etc. the list can goes on. Enjoy!

Ways to debug your jQuery or JavaScript codes

Debugging your client code is rather a normal procedures for any web developers. Everyone will shout Firebug! yeah, me too. But Firebug is great for syntax detection but how about logic problem? In this article i will share with you some of the ways i used to debug my JavaScript or jQuery codes when I'm developing my web application. I will also share with you a trick that i used on my code to alert me that a bug occurs in a particular script since i don't get many helpful users nowadays.

Alert Them Out

The most simple and basic way of debugging is by using JavaScript alert function. This is old but is quite useful sometimes. Especially when you do not want to remember other debugging methods. It's pretty simple, alert the message you want to see. If the alert doesn't appear, this means that the error is before the alert statement. I usually do this when I'm debugging IE although there are tools available for IE.

alert("The Bug Is Somewhere Before ME!")

Log them up

Well, if you are using WebKit browsers for your development (FireFox, Chrome, Safari) you may want to try this.

if (window.console)
  window.console.log("The Bug is killing me");

What this does is to log the string 'The Bug is killing me' into the console such as Firebug. It's always better than using alert and see this infinity loop that keep popping out until you are force to shut down your browser!

Log them with jQuery

The above two methods work both in jQuery and JavaScript. But this only function well in jQuery. This is definitely not something i came up with but its from Dominic Mitchell

  jQuery.fn.log = function (msg) {
      console.log("%s: %o", msg, this);
      return this;
  };

The above creates a function, 'log'. This function will do exactly similar to the one above but the differences is that it format the string a little bit before displaying out to the console. This is good for debugging your long chaining with jQuery. Although the previous method also can be used to debug chaining but it will required an additional line instead of including it into the chaining process. So you can debug this way,

  $(root).find('li.source > input:checkbox').log("sources to uncheck").removeAttr("checked");

Try and catch

In JavaScript, you can try to catch the error in a particular scope. This way, it won't propagate to other section of the code.

try
  {
  //Run some code here
  }
catch(err)
  {
  //Handle errors here
  }

This is pretty good when you are trying to debug one of the many function in your JavaScript.

Catch them all

The last one i am going to show you is to catch any one of the error into a particular function instead of using multiple try and catch.

function handleError(e)
{
alert(’An error has occurred!\n’+e);
return true;
}
window.onerror = handleError;

This will handle any error occurs in your JavaScript code to the function 'handleError'. You will want to use this at the end of your script. Especially if you want to be informed whether a particular function or script has malfunction and the users are not reporting. Basically, what you can do is to gather all information and placed them into a String or JSON. Using ajax to delivery these information to your email or database. This way, your support team will have an idea which part are having problems and your system will be more reliable. (testing doesn't means 100% bug free) The information that you may want to know are usually located at Navigator Object in JavaScript.

Summary

These are the methods i usually look at when debugging my own client script. It might not be everything but i hope it can be useful to some of you out there. Hope you learn something!

Tutorial: How to find width and height of a uploaded image with JavaScript

This is more like a clever trick to find out the height and width of a uploaded image that i would like to share with you. This method most likely will be useful to you when you are dealing with asynchronous uploading which you required the width and height of the image so that you could display the size of the preview box or window. Another usage will be user will have the ability to pre-set the width and height of each images outside the upload function which will resize the uploaded image and you will either required to query the database or look up using server scripting ( both provide redundency). This method will eliminate the need of redundency of query the database or passing the data from server scripting to JavaScript. Instead, we will just required a few sentence of JavaScript to determine the width and height of the uploaded image.

Concept

Let's take an example to demonstrate the concept. Imagine you are trying to perform a asynchronous uploading function that allow users to view their uploaded images on the screen dynamically. So we can use the simple asynchronous uploading function to perform the upload function and use asynchronous complete detection function to inform the user that it has been completed. So once we know that the upload has completed, we want to preview this image to the user right? Assuming that the upload function resize this image randomly. So what is the resize width and height of this image? There are few method that can work this out,

  1. Since we are doing asynchronous upload, we can provide the width and height of the image from the server to the client script
  2. store the width and height of the new image to the database and query it using ajax function
  3. Any other method that required additional work!

This is not efficient at all. What we really need is just JavaScript alone.

  1. Upload the image
  2. Upload completed
  3. display it on the screen
  4. set the width and height to be empty ( reset the width and height to null)
  5. create a new image object and store the new image into it
  6. retrieve the new image object width and height
  7. change the width and height of the display screen to the new image object width and height
  8. Ta-Da~

Simple and clean!

JavaScript

var imgObj = document.getElementById('uploadedImage');
var newImg = new Image();
newImg.src = imgObj.attr('src');

var height = newImg.height;
var width = newImg.width;

imgObj.style.width = width;
imgObj.style.height = height;

I shall skip the codes for PHP and HTML part on how it upload the file to the server and how the server return the images (just have to echo '' after it has been uploaded to the server) to the client as it has been demonstrated on the above link provided. What the JavaScript is trying to do is to retrieve the DOM object of the preview image send in back the server side after uploaded.  It creates a image object and insert that particular preview image into this object. Thus, we have all the information we need stored into this object and placed them into the preview box.

Demo

There are no demo for this method (since i can't store the uploaded images all on the server, it will blow after sometimes) but you can use the demo previously created on asynchronous complete detection function and add a few function into it to make it randomly resize the image you placed into, provide the width and height of each uploaded images via a pop up and resize the iframe according to the new width and height.

Tutorial: How to determine an asynchronous upload completion with JavaScript and PHP

Originally, i wanted to create a progress bar with JavaScript using Ajax as assistance to prompt the server for raw post data. But it seems like PHP doesn't provides raw post data manipulation for its users. Many uses Perl, Flash, Python and etc. which you can see where i am going (Other languages instead of PHP). PHP 5.2 onwards there is an extension to help PHP user manipulate this data but it required the end users or plugin users to adjust their PHP settings to enable certain extension and variables in the PHP setting which is not what i wanted. Therefore, this tutorial is created instead which doesn't required the end users to adjust anything and will be more welcome by programmers. (messing up the setting of PHP can result to security flaws and etc.) But the fall back of this method is that they won't be able to know the progress of upload. (in term of percentage %)

Aim

The aim of this tutorial is to demonstrate a simple method to help programmers who is dealing with iFrame or Ajax (which ever you prefer to call it) upload function to keep track of the upload completion of the file. Simple and Easy is the key objective for this tutorial.

Requirement

There are a few requirement you will need other than reading this post.

  1. Asynchronous upload function - Easy asynchronous upload function using iFrame
  2. JavaScript file - this is the main function to check whether iFrame has complete uploaded the file
  3. Read!

Concept

I like to  have a concept sub section to make my reader understand how it work before showing out all the boring codes. In order to be informed that the upload process has completed, the iFrame will have to show certain message (error and complete message) so that our JavaScript can be informed with the process of the upload function. We will accomplish this with the following steps

  1. Start uploading From iFrame
  2. loading.gif start running
  3. a 'check_complete()' function is being initialize to check the iFrame for message
  4. iFrame shows a message, determine this message (error or success) and output the result accordingly

Asynchronous upload function

Unlike the previous tutorial on asynchronous upload function, i have updated some codes into the previous codes in order demonstrate this tutorial. (Please visit the simplify version of the Asynchronous upload function on the link if you find this complicated)

HTML


<form id="my_form" name="form" action="upload.php" method="POST" enctype="multipart/form-data" >

<div id="main">
<p>
MAX SIZE: 100kb<br/>
ALLOWED FILES EXTENSION: .png, .gif, .jpg, .jpeg<br/>
Other than the above mention rules, all other type of file upload will result in error alert.<br/></p>
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
<input name="my_files" id="my_file" size="27" type="file" />
<input type="button" name="action" value="Upload" onclick="redirect()"/>
<iframe id='my_iframe' name='my_iframe' src="">
</iframe>
</div>
<div id="loading"></div>
</form>

The only differences in this part is the instruction added for the demo to work and a div block box for the loading.gif to appear.

JavaScript


function redirect()
{
document.getElementById('my_form').target = 'my_iframe'; //'my_iframe' is the name of the iframe
document.getElementById('my_form').submit();

var iFrame = document.getElementById("my_iframe");
var loading = document.getElementById("loading");
iFrame.style.display = "none";
iFrame.contentDocument.getElementsByTagName("body")[0].innerHTML = "";
loading.style.display = "block";
checkComplete();
}

In the redirect method which is also the key to use to perform this asynchronous upload function has a few more sentences as shown above which is different from the previous method that only required the first 2 sentence. The above new codes indicate that every time the upload button is pressed, the iFrame should be reminded to be disappeared and the internal of the iFrame should be empty(no message), this sentence is there so that we can perform multiple upload without any problem. Others will required loading.gif to appear to inform the users that it is in progress and the checkComplete() method (the method is located below) is invoked to start monitor the upload completion.

PHP


<?php

$uploaddir = '/images/';
$uploadfile = $uploaddir . basename($_FILES['my_files']['name']);
$file = $_FILES['my_files'];
$allowedExtensions = array("jpg", "png", "gif", "jpeg");
if($file['error'] == UPLOAD_ERR_OK) {
if(isAllowedExtension($file['name'])) {
# Do uploading here

$uploaddir = '/images/';
$uploadfile = getcwd ().$uploaddir . basename($_FILES['my_files']['name']);

//if (move_uploaded_file($_FILES['my_files']['tmp_name'], $uploadfile)) {
echo "success";
//} else {
//  echo "error";
//}
} else {
echo "Invalid file type";
}
} else die("Cannot upload");

function isAllowedExtension($fileName) {
global $allowedExtensions;

return in_array(end(explode(".", $fileName)), $allowedExtensions);
}
?>

What i have added here which is different from the previous version is that i have added a simple validation to validate extension of the files before uploading them into the server in order to demonstrate the different message of this tutorial (error and success).

CSS

Please refer to the demo files if you are interested in the CSS of this demo.

JavaScript

Here is the main method to check for the upload completion from the iFrame.


var checkComplete = function()
{
var iFrame = document.getElementById("my_iframe").contentDocument.getElementsByTagName("body")[0];
var loading = document.getElementById("loading");

if(iFrame.innerHTML == "")
{
setTimeout ( checkComplete, 2000 );
}
else
{
if(iFrame.innerHTML == "success")
{
loading.style.display = "none";
document.getElementById("my_iframe").style.display = "block";
//successful do something here!
}
else
{
loading.style.display = "none";
alert("Error: "+ iFrame.innerHTML);
}
}
}

The first few sentences take  their DOM object for loading.gif and iframe into a variable. Then we check whether the iframe 'body' block contains any message. If there isn't any message we do a recursive loop by calling itself again after 2 second else we hide the loading.gif and show the iframe message if and only if the message in the iframe is 'success' all other message will result in alert to the screen.

Demo

Determine an asynchronous upload completion demo consist of the aim of this post. However, no files will be stored in the server as i am merely providing a demo site to demonstrate this concept. The condition for a success message to appear are stated in the demo site. If you are interested to look up the overall code in this demo, you can download the file at JavaScript-upload-completion-alert. (Please be reminded you will need to setup a webserver in order to test it in your own pc)

function redirect()
{
document.getElementById('my_form').target = 'my_iframe'; //'my_iframe' is the name of the iframe
document.getElementById('my_form').submit();

var iFrame = document.getElementById("my_iframe");
var loading = document.getElementById("loading");
iFrame.style.display = "none";
iFrame.contentDocument.getElementsByTagName("body")[0].innerHTML = "";
loading.style.display = "block";
checkComplete();
}

Tutorial: Easiest way to create a Asynchronous upload file function (ajax upload)

I am going to demo the simplest and easiest way of creating a asynchronous upload file function with JavaScript and PHP.  It is really easy but i take a VERY long time figuring out the method since all the goggling tutorial makes this look complicated and long. The objective is to keep thing simple, VERY SIMPLE.

Concept

Let's face the fact that Ajax cannot do a file upload asynchronously. But let's not go into argument that it can or cannot be done. The method used in this tutorial will be iframe method which is really very easy (slap myself) but i take like few hours to understand what are these people writing with so many unrelated codes. Basically we use a iframe to upload the file instead of the main window to upload it. The sideback of this method is that we cannot monitor the progress of the upload which is why Ajax come into handle in this case but i will not go into detail with the progression monitor of the upload.

Requirement

  1. HTML file - for display purposes
  2. PHP file - for the handling of the upload file
  3. JavaScript - for assisting the whole process
  4. READ

HTML

The HTML part is really very simple as shown below,


<form id="my_form" name="form" action="upload.php" method="POST" enctype="multipart/form-data" >

<div id="main">
<input name="my_files" id="my_file" size="27" type="file" />
<input type="button" name="action" value="Upload" onclick="redirect()"/>
<iframe id='my_iframe' name='my_iframe' src="">
</iframe>
</div>

</form>

I just placed the main code required, the other files can be view overall from the demo attached below. I believe everyone will know what is the above code trying to accomplished. It basically create a iframe, upload box and a button. These 3 item will be wrap around the form so that it can be uploaded by either iframe or uploadbox upon clicked of the button.

P.S: The iframe is not hidden yet, so you guys can see that it has been uploaded over there.

JavaScript

Think asynchronous upload is difficult in the JavaScript part? Think again.


function redirect()
{
document.getElementById('my_form').target = 'my_iframe'; //'my_iframe' is the name of the iframe
document.getElementById('my_form').submit();
}

This is the only function required function you need for Asynchronous upload or ajax upload whatever you call it. What it does is to change the target upload responsible to the iframe instead of the main window frame. Thus, the iframe refresh instead of the main display screen upon the click of the button. ( why do people have to complex stuff, sigh..)

PHP

I believe this part is just about handling the data, so here goes,


$uploaddir = '/images/';
$uploadfile = $uploaddir . basename($_FILES['my_files']['name']);

if (move_uploaded_file($_FILES['my_files']['my_name'], $uploadfile)) {
echo "success";
} else {
echo "error";
}

The above doesn't place constraint on the type of files that is allowed to be placed into the server. You should always add that to avoid unnecessary problem to your application. The above code will move the uploaded file to the upload folder as directed.

Demo

The files did not move the files to any location it will just print out and delete away once it has output successful to the iframe. The demo files can be downloaded from here. You must have to setup a web server to test on it.  You can view the demo here.

P.S: If you are looking for upload completion alert you can find the post at How to detemine an asynchronous upload completion with JavaScript and PHP