How do you upload images now?
You select a file and click upload. Simple right? Except once you select your image you can no longer see what was selected. The name of the file is at the end of the input, and if the input is short, or the file path is deep, you’re not going to see anything useful. You forget what you selected and have not idea what you’re about to upload. “Wait, did I upload a picture of my face or something less professional?”

Let’s make it better.
The key is having an image preview that gets shown before the user needs to commit to saving it. So we ditch the upload button in favor of a save button. Now when a file is selected via the file section input, some AJAX kicks in. The image is processed server side and a thumbnail is loaded onto the existing page.

Doesn’t that feel so much better? We now have a visual representation (imagine that) of the image we selected.
This is particularly useful in larger forms when many fields will be submitted with a single action. It allows the user to review the form before pressing save and see what image (or images) they selected.
How it’s done
Curious how this is done? Here’s the code.
We can use a standard HTML form. We’ll include that as well as an image preview area.
<div id="upload-area">
<div id="preview">
<img width="100px" height="100px" src="/images/icons/128px/zurb.png" id="thumb">
</div>
<form action="/playground/ajax_upload" id="newHotnessForm">
<label>Upload a Picture of Yourself</label>
<input type="file" size="20" id="imageUpload" class=" ">
<button class="button" type="submit">Save</button>
</form>
</div>
The action of the form should point somewhere the process the uploading of the image, regardless of the presence of JavaScript. You may also want to consider only appending the preview markup via JavaScript, as that won’t work without JS.
You’re going to need jQuery and the AJAX Upload jQuery plugin by Andrew Valums. Link them up, making sure jQuery is loaded first. Note that the AJAX Upload plugin does require some configuration and server side stuff to work. Check out that link for details.
<script src="/js/jquery.min.js" type="text/javascript"></script>
<script src="/js/ajaxupload.js" type="text/javascript"></script>
Here is the JavaScript we’re going to add in its entirety.
$(document).ready(function(){
var thumb = $('#thumb');
new AjaxUpload('imageUpload', {
action: $('#newHotnessForm').attr('action'),
name: 'image',
onSubmit: function(file, extension) {
$('#preview').addClass('loading');
},
onComplete: function(file, response) {
thumb.load(function(){
$('#preview').removeClass('loading');
thumb.unbind();
});
thumb.attr('src', response);
}
});
});
Here’s that in plain English:
- Attach plugin behavior to the file input
- Specify the action URL, appropriately pulling it from the action URL in the markup
- When a file is selected, immediately add a class of “loading” to the preview area. This class name, through CSS, hides the image (e.g. .loading img { display: none; } and applies a background image (a spinner)
- Upon AJAX success, remove the loading class and set the src of the image to the response URL that the plugin returns.
Preview Only
Note that the above code deals with the preview functionality only. The file section input still contains the proper file path. So when the user clicks the “Save” button, the form will still need to be processed and handled by whatever server side technology you have ready for that. So yes, you will be essentially uploading the image once (for the preview) and then uploading it again (to save it in a more permanent way).
When you are setting up/configuring the plugin, you’ll set up a directory for a server side script to save uploaded images to. You might want to have that live at somewhere like /images/temp/. That way you know that anything uploaded to that directory is transient and can be cleaned out temporarily to keep the server clean. A empty-that-directory CRON job might be a good idea.
Demo
A working demo is available on ZURB’s site, which also includes more written information. Because of the server side stuff needing to happen, a download unfortunately isn’t practical.
Wondering about other awesome techniques with CSS3 and JavaScript? Check out the ZURB Playground.
ZURB is a close-knit team of interaction designers and strategists that help companies design better products & services. Since 1998 ZURB has helped over 75+ clients including: Facebook, eBay, NYSE, Yahoo, Zazzle, Playlist, Britney Spears, among others.
Thanks for the tips!
Could you recommend me some kind of simple AJAX progress bar upload file script? It seems to be hard to find.
Thanks!
Ajax upload bar is hard to find becose depends on the server side language youre using. If php, give a look at pecl APC.
Else, there are some flash swf uploader, but i dont like flash so i wouldnt raccomand them ;)
You can google html5 upload progress, you’ll find it
I know this may seem a little lazy but couldn’t you just make an old fashioned animated GIF file and use AJAX to add the class ‘loading’, as it is in Chris’ code, which could have a CSS attribute that calls the load animation GIF file until the class is removed. This way won’t give any precise loading information but it does imply that something is happening.
yes, but i would recommend creating a small flash animation similar to a gif. In testing IE froze the gif animation.
I recommend to use any flash based uploader because that will make your life much easier. I recommend these two:
jqUploader
SWFUpload jQuery Plugin
Nice thing about these uploaders is that they both have nice jQuery API :)
Thanks for the remake of this dynamic script that makes our lives as developers much easier – not to mention really impresses our less savvy clients.
Love the “Men In Black” reference.
Great script!
Very neat – but there’s just one slight problem with this approach.
What if the user accidentally choose the wrong file/picture? Normally, you would be able to change that, but now, it get’s uploaded automagically.
This get’s problamatic when the user doesn’t wait until the image is fully uploaded. Try it on the demo: Select one image and after that, another image and so on. All images will be queued and loaded/shown after each other (when they’re processed).
If the user already “submits” before the “final image” is processed, which one will be used as avatar?
Other than that, a great example of usability :) !
This is one of the first things I noticed. I selected a ginormous picture…3mb…and while it was uploading verrrry slowly, I realized I had a smaller version of it already. The only solution I found was to refresh the page and start over.
Definitely needs a “cancel” button somewhere in there.
To further touch on what Marco is saying, the solution is one part of a larger puzzle. Even though this is great front-end solution, it fails to address how to handle this on the server side.
You can make an assumption of what the “Save” button does and some of the DB queries it might set in motion, but you also need to take account for images that will be left on your server if multiple files are upload, or how to delete them if you intend to save only one.
Maybe round 2 of this article :)
The AJAX Upload Plugin will save files to a directory, as I mentioned in the article, probably best to save it to a TEMP directory. Clicking the save button will save it, presumably, to a more permanent home. What the form actually uploads is whatever the file path currently is in the input.
I don’t think it’s as confusing as it is being made out to be here.
I agree, it’s not hard to get around the delete issue.
Once the user has saved it, you can keep the file name, and preview/thumbnail if you like, then add a delete radio (or whatever), for that photo.
This has been the source of much pondering for me at my site – I still haven’t nailed it, but this demo helps.
Tim
I used this on a site but in Chrome it would say “File not chosen” even though i had selected one. Has this been resolved?
Hey Fiaz – Thanks for the inquiry. The plugin works, this display message is just a little confusing in Chrome. It’s a Chrome related issue. We’ll see what we can do improve this.
Thanks for chiming in! How do you like our other ZURBplayground techniques?
-Dmitry
I have been looking for Ajax image up-loaders and even looked at the ZURB site, but I was more specifically looking for an upload with a resize, crop function — (there doesn’t seem to be any code around the web)
For the average Joe on the web (maybe that’s me?) it isn’t clear that the image isn’t saved when it is previewed, you see the image on the page so assume it is uploaded?
Unfortunately it doesn’t work with Opera 10.53.
If I am not mistaken it was there on Zurb before also, I guess I’ve seen it.
Why don’t you do this: when the user chooses the picture, the picture location will be placed inside the preview ‘img’ tag like:
<img src="file://c:/SomeImage.png" />
and if the user likes it, s/he can upload it.
I quite like this idea. I don’t think I’ve ever seen it done that way. I wonder if there is some barrier that prevents that (like browser inconsistencies in how the provide the file path), or if people just randomly haven’t been smart enough to try it…
I love this idea!!!
I’m going to test in some different browsers after work today.
It is a geniusly simple idea! Will look forward to finding out if it works.
I can’t see why this wouldn’t work, I was thinking this too when I read the article. It would be very responsive too, much faster.
The only problem I can forsee is with secure pages and Internet Explorer warning about mixing secure & non-secure items.
Just found this: http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_26302820.html, apparently it looks like it might not be possible.
I’ve been doing some research on this and it’s not looking good. There is a workaround with Firefox which gives you access to a function to grab the image data as a data URI. IE and Opera give you a weird /fakepath/ value, and Safari/Chrome won’t give you any value at all for a file input.
Well, I’m glad somebody said it, because, this entire concept seems useless to me. Why waste all these resources client AND server side, when you can just point the browser to the file locally? *scratches head*
Yup, was just scrolling down the page looking for this before I’d comment the same.
Tested in a HTTP-environment in Firefox 2 on a Mac. (not in a PC, and not with HTTPS, dunno if that would be a problem tho).
Hehe, this comment just made the whole article pointless.
A mootools alternative that also supports FF drag and drop: http://mootools.standupweb.net/dragndrop.php
Slight issue/more of a question… no iPad or iPhone support for choosing a photo to upload through this method… My inital thought is adding an input field to the “New Hotness”, that will allow copy and paste of filename, but that won’t really solve the issue in a user friendly way (they’d have to email the photo to themselves and then go through the forwarding the email motions to get the filename access… anyone have a more elegant solution to this?
Isn’t it better to use a technique where the file is uploaded using the hidden iframe method?
You can still preview the image but, with a bit of server side scripting, you can keep this file on form submission without having to wait for the file to be uploaded for a second time (the server side scripting also needs to fall back if the form uploads a file normally as well).
The preview-upload (which returns the URL to the image) could be used on submission. Let it send some hash code too.
if the user didn’t browse again since the last succesfull preview-call then send the hash code of the preview so that the server won’t be downloading it again, but simple moves the earlier file to a permanent home from the temp. dir.
If I was building it from scratch that is what I would try and do too. If the file has already been uploaded one via AJAX, clicking save should just trigger an action to move that file to the permanent location and be done with it.
With regards to the “cleanup issue”: have a DB consisting of temp file names and upload timestamps. On upload complete, write the temp file and timestamp to the DB. On submit, remove it from the DB. Have a cron script that runs daily/weekly that queries the uploads from the prior day/week and delete those files. These will be all the images that were uploaded and never submitted. Very, very simple script/db and quite effective.
This is good info! I especially like the MIB reference.
K
Once you have submitted the form, the temporary preview file can be deleted via PHP or other server-side language.
huh;) this article saved my life, great stuff specialy because its done with Ajax. Keep up the good work and b.r.!
Here’s how I implemented it. I have four image upload boxes on my site, and as each one is clicked an image is automatically uploaded.
My form doesn’t have any file inputs at all, I applied the ajax upload to an upload icon, and after the image is uploaded, I have a php script that creates a zoom cropped full version, and a 100×100 thumbnail in a temp folder. The thumbnail path is returned in the response variable, and I use that to update a thumbnail image in the form, and insert the the response into a hidden field. I then hide the upload icon and replace it with a delete icon. If the delete icon is clicked, I reset the thumbnail and clear out the hidden field and then hide the delete icon and show the upload icon.
When the form is submitted, the receiving script then reads the hidden inputs and moves those images and thumbnails out of the temp folder into their permanent folder.
I have a cron job running that checks the modification time of each file in the temp folder and compares it to the current time. If the difference is greater than 14400, I delete the file (4 hours old). I don’t just wipe the folder because I may end up deleting an image of a user who is still using the form. If it’s taking someone more than four hours to submit a form with less than 10 fields, they have bigger problems than their uploads disappearing.
And for those who say I should have file inputs in case someone has javascript off – my site is a google maps mashup so if they don’t have javascript on, they can’t use my site anyways.
My only question is, why, after the iframe upload is complete, does my status bar still show a progress bar even though all requests are complete?
Thanks
B
can i use this ui in asp.net ?
I am using jUploadify in this project here (u can only see it if you are registered, in your profile page (german)) -> http://1click.at/23s6h1
Is this work in google chrome ?
Don’t think the demo works any more, haven’t tested the actual script myself yet. But all i ever see is a lovely photo of Chuck Norris, tested it in Chrome, Safari, Opera, IE7+8 on XP and 7 :)
Here is another fun Ajax Thingy..
HTML5 Ajax Website http://bit.ly/9hXmZt
thanks for helping me
Hi just to check if this works in IE, and can I also check the min version required for JQuery? Saw from the demo they are using 1.7.1; will it work if I am using jQuery 1.4.4?
The page with the AjaxUpload plugin isn’t operational. Are there any other sources for that plug in?