Skip to content

June 12, 2009

8

Ajax: a simplified version of file upload form using IFRAME

by Joe Kuan

I have been trying to create file upload form in Ajax. Most of the tutorials I found are using <IFRAME> technique as a hidden frame. In OpenJS, it gives an excellent tutorial. In a nutshell, the file upload form redirects the reload action into the hidden frame. Then uses the top window to fetch the results (using JSON) when the hidden frame is loaded which indicates a file has been uploaded. This technique involves setting up the onload and onsubmit event handlers while the main page is loaded.

However, my scenario is slightly different that the <DIV> box in my page is inserted dynamically with different forms, like Ajax.Updater(‘action_box’, ‘action_form.html’), during the users navigation. So that I cannot rely on setting up onsubmit and onLoad event handlers when the main page is loaded. Here is a slightly modified and simplified version of the one in OpenJS to cater for this scenario. It is imperative that you understand the OpenJS tutorial first.

First of all, we have a HTML file upload form like this:

<FORM action='save_upload.php' method=post enctype='multipart/form-data' target=hidden_upload>
<DIV><input type=file name='upload_scn' class=file_upload></DIV>
<INPUT type=submit name=submit value=Upload />
<IFRAME id=hidden_upload name=hidden_upload src='' onLoad='uploadDone("hidden_upload")'
        style='width:0;height:0;border:0px solid #fff'></IFRAME>
</FORM>

Note that the key differences are the target and onLoad attributes in FORM and IFRAME tags respectively. Once the above HTML code is loaded, the web client uploads the file to the server. The web server processes the file and sends the result in JSON to the client. The target attribute in the FORM tells the client to load the result in the hidden IFRAME. After the result is displayed in the hidden IFRAME, the onLoad event is triggered and executes the main javascript uploadDone function.

The uploadDone function is defined as below and it is loaded in the main page javascript section.

function getFrameByName(name) {
  for (var i = 0; i < frames.length; i++)
    if (frames[i].name == name)
      return frames[i];

  return null;
}

/* Same as the one defined in OpenJS */
function uploadDone(name) {
   var frame = getFrameByName(name);
   if (frame) {
     ret = frame.document.getElementsByTagName("body")[0].innerHTML;

     /* If we got JSON, try to inspect it and display the result */
     if (ret.length) {
       /* Convert from JSON to Javascript object */
       var json = eval("("+ret+")");
       /* Process data in json ... */
       ....
     }
  }
}
 

On the server side, the save_upload.php page is simply defined like this:

<?php
  $target_filepath = "/tmp/" . basename($_FILES['upload_scn']['name']);

  if (move_uploaded_file($_FILES['upload_scn']['tmp_name'], $target_filepath)) {
    $result = ....
  }

echo json_encode($result);
?>

At the time of writing, this example works on IE 8, Safari 4 and Firefox 3. Hope this helps.

I work for iTrinegy and here are my other Javascript blogs

8 Comments Post a comment
  1. Ulfat
    Jul 3 2009

    Hi!
    Good Example.Thanks.
    I have a problem.I am using ASP.net.On my page I have an html form which contains an Iframe.Action of form is set to an address of SlideShare API and target set to iframe name.When i submit form the I can see the response loaded in IFrame.But when I try to get this response in javascript , I get nothing.

    frame.document.getElementsByTagName(“body”)[0].innerHTML;
    was not working

    Also frame.innerHTML was not working.
    Is there a way to check the response.In my case it is an xml returned by API.

    Regards

    Reply
    • Joe Kuan
      Jul 3 2009

      frame.innerHTML will not work because frame is a type of window object.

      innerHTML should work as it is supported by both IE and Firefox. It is likely something wrong before that.

      A quick way is to print the object out, try this and see which part is undefined
      alert(‘1- ‘ + frame + ‘. 2-‘ + frame.document + ‘. 3-‘ + frame.document.getElementsByTagName(“body”)[0]);

      I have zero experience in ASP.net, so I am not really sure what the real problem is.

      Reply
  2. Ulfat
    Jul 7 2009

    Hi!
    thanks for reply.
    When IFrame loads first time it is okay
    alert(“1- ” + frame );
    alert(“2- ” + frame.document );
    (frame.document.getElementsByTagName(“body”)[0]);

    are working .But when it loads response then it throws JavaScript error “Permissionis denied for property window.document” for document.frame”.

    Reply
  3. Joe Kuan
    Jul 7 2009

    Very strange.
    1) Which browser do u use?
    2) Try printing frame.name to double make sure the frame is the one you are looking for.
    3) Try printing out frame.document.getElementsByTagName(‘body’) and see whether the same error.
    4) Try printing out
    frame.document.body and see what it is

    If you still can’t find the problem, then post ur JS script here but I can’t guarantee I have the solution either.

    Reply
  4. Hemal Patel
    Mar 8 2010

    Very useful post. specially with Classic ASP. Thanks!

    Reply
  5. dally, liu
    Mar 19 2010

    You need to set domain to be the same as parent window. that will resolve access deny issue. Although setting Window.domain is not recommended for security reason

    Reply
  6. Yadab Raj Ojha
    Jun 3 2013

    Very nice article..thank you it help me a lot while image upload using java + spring mvc architecture.

    Reply
  7. amer deep
    Jul 24 2014

    Very nice article, seamlessly working on all the browser, thanks for sharing this. I am using C# as backend and it helped me to resolve IE issues :).

    Reply

Leave a reply to Ulfat Cancel reply

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments