AJAX FILE UPLOAD – Uploading local files with AJAX/Javascript to a server

Many people say uploading files with AJAX is impossible! Well, they’re wrong 🙂

Granted this solution only works with FireFox/Mozilla. And the user has to change a setting in “about:config” and accept the advanced access privileges.

Anyway, such an AJAX file upload is only suitable for restricted area stuff, such as Content Management Systems, Group-Ware etc., so users can be briefed before actually using it.

Open about:config and check that

signed.applets.codebase_principal_support

is set to “true”

Otherwise Firefox will display something like this

Error: uncaught exception: A script from "http://www.captain.at"
was denied UniversalXPConnect privileges.

Also make sure you check the checkbox “Remember this decision”, when FireFox will display this message

A script from "http://www.captain.at" is requesting enhanced abilities that are
UNSAFE and could be used to compromise your machine or data:

Run or install software on your machine

Allow these abilities only if you trust this source to be free of viruses or malicious
programs.
[ ] Remember this decision

and click “Allow”, otherwise you have to click “Allow” everytime you upload a file.

The example itself is rather straightforward:

We use some Components.classes and Components.interfaces stuff to open the local file from within FireFox/Mozilla – we read the file, construct our request body for the POST request and send the whole data with an AJAX “multipart/form-data” request.

NOTE about encoding the local files:

Since we also want to upload binary files, we need to encode (javascript “escape”) the file content. This is basically encoding a string for use in an URL. On the server, after uploading the file we need to decode (“urldecode”) the file. “escape” does not encode the plus sign “+”, but on the server PHP’s “urldecode” interprets any “+” and space. So we need an additional preg_replace to replace any “+” to the HEX value “%2B”.

This is a little annoying, since escaping large files (up to 1MB it is still fast) with javascript can hang the browser for a few seconds. The problem here is that the AJAX object XMLHttpRequest doesn’t seem to be able to handle binary data.

ADVANTAGES:

If you upload images and process them on the server, it is common that the server stops the script due too much memory consumption and/or the runtime limit has been exceeded. In such a case PHP is just returning an error message (“Fatal error: memory limit exceeded” or “Fatal error: running too long” or whatever) and the user usually has to back up with the browser back button to repeat the procedure with a smaller image. With AJAX you can check the returned string for errors and if an error has occured, notify the user gracefully.

A possible extension to this example would be:
Let the user select a directory with a custom “directory-browser” or one file in a directory with the regular file-dialog as shown here, then parse the directory automatically for file with a certain extension and upload them in a bulk.

index.html



post.php

print_r($_FILES);
?>

print_r($_POST); $fpath = "/tmp/"; // move (actually just rename) the temporary file to the real name move_uploaded_file ( $_FILES{myfile}{tmp_name}, $fpath.$_FILES{myfile}{name} ); // convert the uploaded file back to binary // javascript "escape" does not encode the plus sign "+", but "urldecode" // in PHP make a space " ". So replace any "+" in the file with %2B first $filename = $fpath.$_FILES{myfile}{name}; $handle = fopen($filename, "r"); $contents = fread($handle, filesize($filename)); fclose($handle); $contents = preg_replace("/\+/", "%2B", $contents); $handle = fopen($filename, "w"); fwrite($handle, urldecode($contents)); fclose($handle); ?>
Ashesh

सयौ थुङ्गा फूलका हामी एउटै माला नेपाली, Welcome to my webpage. I'm from the Himalayan Country of Nepal. Well talking about me, I like mostly Web programming and Designing and furthermore I like Philosophical literature, Photography, Social networking. And I am Romantic and Sentimental person to some extent. Read more...

View Comments