50

I'm trying to make ajax file upload . I read that it is not possible to do that without using iframe .
I wrote :

<iframe id="uploadTrg" name="uploadTrg" height="0" width="0" frameborder="0" scrolling="yes"></iframe>
<form id="myForm" action="file-component" method="post" enctype="multipart/form-data"  target="uploadTrg">
File: <input type="file" name="file">
<input type="submit" value="Submit" id="submitBtn"/>
</form>

and using jquery form plugin :

$('#myForm').ajaxForm({
    dataType:  'json',
    success:   function(data){
        alert(data.toSource());
    }
});

The Result :

the file is uploaded successfully and I can see the uploaded file , but a dialog box appears :

alt text

since I send back a json result to display the file name + size etc ..

My Question : How can I use the iFrame to be able to make " ajax file upload".

Note:

  1. I don't prefer to use special plugin to upload file , if there is more appropriate/easier solutions.
  2. I use jsp/servlets as a server-side language .. but I think it does not make sense which language I use .

Thanks

Community
  • 1
  • 1
Abdullah
  • 5,445
  • 10
  • 41
  • 48
  • In your #1, are you referring to jQuery plugins, or you do you mean Flash/Silverlight? – Nick Craver May 26 '10 at 02:18
  • I design a more simplified ajax style file upload page without using JavaScript. I place a hidden iFrame just before the form tag. Please read the following. http://ramui.com/articles/ajax-file-upload-using-iframe.html –  Dec 06 '11 at 13:37

2 Answers2

96

I will answer my question , I think I found the solution. These are the steps that I followed to achieve the goal :

  1. Make the attribute "target" of the form point to " iframe " .
  2. Use a normal HTML request ( not Asynchronous/Ajax request ) to submit the form.
  3. Because the target frame is iframe , the whole page will not be refreshed - just the iframe.
  4. Once iframe onload event happens (capture that event using Javascript) then do what you want, e.g. You can send back a request to list recent uploaded file info.

The final code looks like this:

    <!-- Attach a file -->

    <iframe id="uploadTrg" name="uploadTrg" height="0" width="0" frameborder="0" scrolling="yes"></iframe>

    <form id="myForm" action="http://example.com/file-upload-service" method="post" enctype="multipart/form-data"  target="uploadTrg">

        File: <input type="file" name="file">
        <input type="submit" value="Submit" id="submitBtn"/>

    </form>

    <div id="ajaxResultTest"></div>

javascript :

$("iframe").load(function(){
    // ok , now you know that the file is uploaded , you can do what you want , for example tell the user that the file is uploaded 
    alert("The file is uploaded");

    // or you can has your own technique to display the uploaded file name + id ? 
    $.post('http://example.com/file-upload-service?do=getLastFile',null,function(attachment){

       // add the last uploaded file , so the user can see the uploaded files
       $("#ajaxResultTest").append("<h4>" + attachment.name + ":" + attachment.id "</h4>");

    },'json');
});
Abdullah
  • 5,445
  • 10
  • 41
  • 48
  • 5
    The target attribute is deprecated (http://www.w3schools.com/TAGS/att_form_target.asp). I am beginning to believe that one must either used deprecated (X)HTML or Flash/etc. to accomplish what /should be/ very primitive functionality. – Spain Train Aug 13 '10 at 20:33
  • +1 for your extremely good solution. But steps are not very clear. You should probably remove extra code and just explain the main parts which are explained here: http://ramui.com/articles/ajax-file-upload-using-iframe.html – iMatoria Jul 05 '13 at 09:05
  • 1
    @iMatoria You are right , I removed the extra code and I tried to clarify the answer a little bit more. – Abdullah Jul 05 '13 at 23:10
  • 1
    @MikeS, I checked MDN and I don't see where it says the target attribute in HTML form element is deprecated. MDN is a much more reliable resource than W3Schools so its possible you are mistaken. Here is the link: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form – Gautham C. Jan 14 '14 at 18:39
  • @GauthamC. It's in HTML5 and HTML4.01 loose (http://www.w3.org/TR/html401/loose.dtd), but not HTML4.01 strict (http://www.w3.org/TR/html401/strict.dtd). In the 3.5 years since this was asked, many libs for doing this have matured. I *strongly* recommend you not implement this manually. – Spain Train Jan 15 '14 at 05:09
  • @MikeS, wanted to implement it manually just for the sake of learning. I will look into the source for these libraries. Thanks for the heads up! – Gautham C. Jan 15 '14 at 19:25
  • 3
    @SpainTrain The target attribute is supported in HTML5. ;) – Warface Feb 21 '14 at 21:06
  • 2
    Nice explaination. However instead of making another ajax post, you could echo a response in the iframe content and then read it in js – Qlimax May 27 '15 at 10:06
  • Thanks For helping me. Been looking for a way to do this for like a week. – user875139 Aug 06 '15 at 18:31
4

This example taken from BugKiller. complete working example which allows you to upload a logo and see it immediately in the html page, following which the upload value gets cleared:

html:

<form id="uploadForm" method="post" enctype="multipart/form-data"  target="uploadTrg">
  <div id="fileUploadWrapper"><input type="file" name="file" id="fileUpload"></div>
  <input type="submit" value="Upload" id="submitBtn"/>
</form>
<iframe id="uploadTrg" name="uploadTrg" height="0" width="0" frameborder="0" scrolling="no" style="display:none"></iframe>
<img id="imgLogo" style="border-width:0px;" />

javascript:

$(document).ready(function () {
  var companynumber = '12345'; //get this from the database
  var logoUploadUrl = 'UploadHandler.aspx?logoupload=true&companynumber=' + companynumber ;
  $("#uploadForm").attr("action", logoUploadUrl);

  $("#uploadTrg").load(function () {
    //upload complete

    //only way to reset contents of file upload control is to recreate it
    $("#fileUploadWrapper").html('<input type="file" name="file" id="fileUpload">');

    //reload the logo url, add ticks on the end so browser reloads it
    var ticks = ((new Date().getTime() * 10000) + 621355968000000000);
    var logoUrl = 'images/clients/' + companynumber + '/client.gif?' + ticks;
    $("#imgLogo").attr('src', logoUrl);
  });
});

upload handler code behind (C#):

namespace MyWebApp {
    public partial class UploadHandler : System.Web.UI.Page {

        protected void Page_Load(object sender, EventArgs e) {
          if (Request.Params["logoupload"] != null) {
            string companynumber = Request.Params["companynumber"];
            string savePath = Server.MapPath("\\images") + "\\clients\\" + companynumber + "\\client.gif";
            if (File.Exists(savePath))
                File.Delete(savePath);
            //save the file to the server 
            Request.Files[0].SaveAs(savePath);

            Response.Write("OK");
            Response.Flush();
            Response.End();
          }
       }
}
JJ_Coder4Hire
  • 4,706
  • 1
  • 37
  • 25