Ajax form upload local image file without refresh

The code example below performs following tasks:

  • Upload multiple image files without refresh page.
  • Control maximum number of image files to be uploaded.
  • Instantly review uploaded images.

See it in action here

Download source code

Basic idea:

You have a Form #1 with input element with type “file” to let user to select what images to be uploaded. Also, you need a hidden Form #2 and hidden iframe to do the upload action implicitly. When user select a file, the value of input element needed in Form #2. However, for security reason, browsers are not allow us to manipulate the value of input element, therefore directly copy value of input element to another is not the way to achieve our goal. But, how about copy the whole input element to Form #2? Here is the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
 
<script  type="text/javascript">
var frameId = 'frame_ID';         //hidden frame id
var jFrame = null;                //hidden frame object
var formId = 'form_ID';           //hidden form id
var jForm = null;                 //hidden form object
var fileMax = 3;                  //maximum number of file to be uploaded
var fileCount = 0;                //file counter
var uploadUrl = "save.php";       //where to handle uploaded image
 
 
$(document).ready(function(){                     
 
jForm = createForm(formId);            //create hidden form
jFrame = createUploadIframe(frameId);  //create hidden iframe
 
//append hidden form to hidden iframe
jForm.appendTo('body');         
jForm.attr('target',frameId);          //make form target to iframe
 
//bind onchange function to input element
$("#inp").bind('change',startUpload); 
 
function startUpload(){
   if(jForm!=null){               
      jForm.remove();                        //re-create hidden form
      jForm = createForm(formId);
      jForm.appendTo('body');
      jForm.attr('target',frameId);
   }
 
   var newElement = $(this).clone(true);   //clone input element object
   newElement.bind('change',startUpload);  //bind onchange function. detect iframe changes
   newElement.insertAfter($(this));        //insert clone object to current input element object
   $(this).appendTo(jForm);                   
 
   jForm.submit();                         //let's upload the file
 
   jFrame.unbind('load');                  
   jFrame.load(function(){        //bind onload function to hidden iframe
 
      //get response message from hidden iframe
      var myFrame = document.getElementById($(this).attr('name'));   
      var response = $(myFrame.contentWindow.document.body).text();
 
      /*
      * you may handle upload status from reponse message.
      * in this example, upload succeeded if message contains ".gif" , otherwise, alert reponse message
      */
 
      if(response.indexOf('.gif')!=-1){ //upload successfully
 
         //show thumbnails, add text box with file name
         addUpload(Math.floor(Math.random()*100),response);   
         fileCount++;
         if(fileCount >= fileMax){   //reach maximum upload file, disable input element
            $("#inp").attr('disabled','disable');
         }
      }else{  //error
         alert(response);
      }
   });
}
 
 
});
 
function createUploadIframe(id){
   //set top and left to make form invisible
   return $('<iframe width="300" height="200" name="' + id + '" id="' + id + '"></iframe>')
         .css({position: 'absolute',top: '270px',left: '450px',border:'1px solid #f00'})
         .appendTo('body');
}
 
function createForm(formId) {
      return $('<form method="post" action="'+uploadUrl+'" name="' + formId + '" id="' + formId + 
            '" enctype="multipart/form-data" style="position:absolute;border:1px solid #f00;'+
            'width:300px;height:100px;left:450px;top:150px;padding:5px">' +
            '<strong>You should hide red blocks</strong><br><br></form>');
}
 
function addUpload(id,img){
   var div = $(document.createElement('div')).attr('id',id);
 
   //add uploaded image
   div.html("<img src='"+img+"'><br />");
 
   //add text box
   var fileName = img.substring(img.lastIndexOf("/")+1);
   var txtbx = $(document.createElement('input')).attr('name','img[]').attr('type','text').val(fileName);
   /* you may want to change textbox to a hidden field in production */
   //var txtbx = $(document.createElement('input')).attr('name','img[]').attr('type','hidden').val(fileName);
   txtbx.appendTo(div);
 
 
   //add remove thumbnail link
   var rem = $(document.createElement('a'))
                               .attr('alt',id)
                               .attr('href','javascript:;')
                               .text("Remove").click(removeUpload);      
   rem.appendTo(div);
 
   //add to the page
   div.appendTo("#uploaded_thumb");
}
 
function removeUpload(e){
   var removeId = $(e.target).attr('alt');
   $('#'+removeId).remove();
   if(fileCount>0) fileCount--;
   $("#inp").removeAttr('disabled');
}
</script>
 
</head>
<body>
  <form>   
   <div id='uploaded_thumb'></div>
 
   <div style='padding-top:20px'>
   upload a small GIF <input type='file' name='image' id='inp'>
   </div>
  </form>
</body>
</html>
  • Share/Save/Bookmark

22 Responses to “Ajax form upload local image file without refresh”

  1. [...] The code example below performs following tasks: Upload multiple image files without refresh page. Here is the original: Ajax form upload local image file without refresh [...]

  2. hoolio says:

    Doesnt work for me! I just get an error in the iframe and am alerted that save.php cannot be found.

    Would love it if you explained it a bit more clearly or even posted up a working demo.

    Anyways,

  3. Rick says:

    Hi hoolio,

    save.php is where you should handle uploaded images from the form. It should be located in your server, eg. http://your-domain.com/save.php

    I will post a working demo later.

    Thanks, hoolio.

  4. es says:

    Remove image – don’t remove image from server :(

  5. rick says:

    Hi es,

    This demonstration only shows how to handle upload images. If you want to implement image removal from server, you must add another ajax call within function removeUpload(e){} and pass file name which need to be deleted. On server side, simple, just unlink() the file.

  6. Mark Baker says:

    Hi there, I am trying to add a submit button rather than use the the change method on line 25 of the javascript

    Ive added a submit button with the id=’test’ and changed the function to a click rather than change.

    //bind onchange function to input element
    $(”#test”).bind(’click’,startUpload);

    when I try this the script loads but all I get back is an empty alert box? any ideas what I am doing wrong? – Great example BTW

  7. rick says:

    Hi Mark,

    Thank you for your comment.
    Let me clear something first. Does onchange works perfectly on your side? (I mean images are successfully uploaded to sever?)
    If it works, the button should work too.
    You may feel free to echo any message on “uploadUrl = ’save.php’;”, those messages will appear on alert box. By this way, you can debug if save image works or not.

  8. Mark Baker says:

    Hi Rick, thanks for getting back to me so quickly.

    Yes onchange is working perfectly and images are uploading fine, just for my purpose I really need an additional button as well the file input. Ive tried a few different ways this evening but still no luck? Ive even tried adding the function startUpload as an Onclick from the button in the form instead of the bind method and this also failed.
    Help?

  9. rick says:

    It sounds weird. Can you post your test url here so I can take a look?

    By the way, please make sure this line
    $(”#test”).bind(’click’,startUpload);
    should place inside of
    $(document).ready(function(){ …….. });

  10. Marco says:

    Hi all, many thanks for the script, i’m testing it but it seems to work only for Firefox. IE can’t show the picture immediatly like FF, i’v to change the focus and come back to the ajax form…
    I tried to change line 24 to
    $(”#inp”).bind(($.browser.msie ? “propertychange” : “change”),startUpload); //bind onchange function to input element

    but it works only for the first image… could you help me?

    Thanks

  11. dmort says:

    hello, great script. I want to add 3 photos to this form.
    I have been trying, but the crop thing is too complicated for more than 1 photo.
    Do you have any ideas how I can just show a preview in each photo div?
    How much would you charge to help me out?

    Thanks

    Dennis

  12. AdRock says:

    This is exactly what I’ve been looking for.

    All the other examples I’ve seen uses a form action button to the upload/save.php where in fact I want to have my own action. Your example lets me do what i want so i can save data in a database.

    Excellent work and thanks for sharing

  13. jquerybeginner says:

    What a neat and clear explanation! I went through so many websites in search of what I was looking for: to upload files to the database, but none explained to me so clearly what they were doing or why. Now I understand what they all have been doing. Thanks to you!

  14. anotherbeginner says:

    i have a problem only with firefox 3.6, 3.5 (both on windows and ubuntu) but not with firefox 4 beta or firefox 2.0, when i try to generate unique image name in save.php
    $_FILES['image']['name'] = mt_rand(222,999).’.jpg’;
    $uploadfile = $_FILES['image']['name'];

    the first uploaded image is generated as normal, but the second is generated two times, and the third is generated three times, so after 3 uploads i see 3 images in browser, but on server i have 6 images (1+2+3). is there a way to correct this?

  15. [...] getting a image upload field to work so people can upload a pic of the fish. I’m using this http://www.fengcool.com/2009/06/ajax-form-upload-local-image-file-without-refresh/ and i can get the image to upload but not show up in the jot-comment section. So i need the [...]

  16. Marc says:

    if(response.indexOf(’.gif’)!=-1){ //upload successfully

    How to make it accept multipe (jpg, jpeg, gif & png), already did it on save.php but need to know how to do it on ajax side.

  17. Have you tried to change the line

    if(response.indexOf(’.gif’)!=-1){ //upload successfully

    to

    if(response.indexOf(’.gif’)!=-1 || response.indexOf(’.jpg’)!=-1 || response.indexOf(’.jpeg’)!=-1 || response.indexOf(’.png’)!=-1){ //upload successfully

  18. [alfa] says:

    How to add another ajax call within function removeUpload(e){} to remove image from server?

  19. rick says:

    Hi alfa,

    You can make an extra ajax call to remove the file from server.
    This is an example. I have tested, hope this can help you.

    function removeUpload(e){
    var removeId = $(e.target).attr(’alt’);
    // get image src path
    var imagePath = $(’#'+removeId).find(’img’).attr(’src’);

    $(’#'+removeId).remove();
    if(fileCount>0) fileCount–;
    $(”#inp”).removeAttr(’disabled’);

    // send image src to server
    $.get( “http://your_domain/your_file.php” , {’removeFileName’:imagePath} );
    }

  20. [alfa] says:

    Thank you very much rick…It works perfectly!
    Now your code is complete.

Leave a Reply