Ajax File Upload Response Handling

Ajax File Upload Response Handling

A while ago, I wrote an article on Ajax File Uploading - the
method of uploading a file without refreshing the page using a hidden iframe. Since then people wanted to know how to get information about the uploaded file back into the javascript
application. Consider this the second part of that article - this post will tell you how to get the information about the uploaded file in javascript.

A Sample Application

For example, say you are building a photo gallery. When a user uploads an image(using the above mentioned ajax method), you
want to get its name and file size from the server side. First, lets create the Javascript uploading script(for explanation on this part, see the Ajax
File Upload article
)...

The Code

<script type="text/javascript">
function init() {
	document.getElementById("file_upload_form").onsubmit=function() {
		document.getElementById("file_upload_form").target = "upload_target";
	}
}
</script>

<form id="file_upload_form" method="post" enctype="multipart/form-data" action="upload.php">
<input name="file" id="file" size="27" type="file" /><br />
<input type="submit" name="action" value="Upload Image" /><br />
<iframe id="upload_target" name="upload_target" src="" style="width:100px;height:100px;border:1px solid #ccc;"></iframe>
</form>
<div id="image_details"></div>

And the server side(PHP in this case) script will look something like this...

<?php
list($name,$result) = upload('file','image_uploads','jpg,jpeg,gif,png');
if($name) { // Upload Successful
	$details = stat("image_uploads/$name");
	$size = $details['size'] / 1024;
	print json_encode(array(
		"success"	=>	$result,
		"failure"	=>	false,
		"file_name"	=>	$name,	// Name of the file - JS should get this value
		"size"		=>	$size	// Size of the file - JS should get this as well.
	));
} else { // Upload failed for some reason.
	print json_encode(array(
		"success"	=>	false,
		"failure"	=>	$result,
	));
}

Here we are printing the data that should be given to JS directly into the iframe. Javascript can access this data by accessing the
iframe's DOM. Lets add that part to the JS code...


function init() {
	document.getElementById("file_upload_form").onsubmit=function() {
		document.getElementById("file_upload_form").target = "upload_target";
		document.getElementById("upload_target").onload = uploadDone; //This function should be called when the iframe has compleated loading
			// That will happen when the file is completely uploaded and the server has returned the data we need.
	}
}

function uploadDone() { //Function will be called when iframe is loaded
	var ret = frames['upload_target'].document.getElementsByTagName("body")[0].innerHTML;
	var data = eval("("+ret+")"); //Parse JSON // Read the below explanations before passing judgment on me

	if(data.success) { //This part happens when the image gets uploaded.
		document.getElementById("image_details").innerHTML = "<img src='image_uploads/" + data.file_name + "' /><br />Size: " + data.size + " KB";
	}
	else if(data.failure) { //Upload failed - show user the reason.
		alert("Upload Failed: " + data.failure);
	}
}

Explanation

Lets see whats happening here - a play by play commentary...

document.getElementById("upload_target").onload = uploadDone;

Set an event handler that will be called when the iframe has compleated loading. That will happen when the file is completely
uploaded and the server has returned the data we need. Now lets see the function uploadDone().

var ret = frames['upload_target'].document.getElementsByTagName("body")[0].innerHTML;
var data = eval("("+ret+")");

These two lines are an eyesore. No - it goes beyond 'eyesore' - this is an abomination. If these lines causes you to gouge out your eyes and run for the hills, I can understand completely. I had to
wash my hands after writing those lines. Twice.

var ret = frames['upload_target'].document.getElementsByTagName("body")[0].innerHTML;

This will get the data the server side script put in the iframe. This line cannot be avoided as far as I know. You can write
it in different ways - but in the end, you will have to take the innerHTML or the nodeValue or something of the body element of the iframe. I used the smallest code in the sample. Even if you specify the Content type of the iframe page as text/plain, the browser
will 'domify' it.

One other thing - in frames['upload_target'] the 'upload_target' is the name
of the iframe - not the ID. Its a gotcha you need to be aware of.

var data = eval("("+ret+")");

Thankfully, this line can be avoided - you can use some other format(in this particular case the best format might be plain HTML) so that you don't have to parse a string that comes out of innerHTML.
Or you can use CSV. Or plain text. Or JSON as we are doing right now - just parse it without using eval().
Reason I choose it? Smallest code - and easier to understand.

Now we have a working system. The files are uploaded and data reaches the client side. Everything works perfectly. Oh, how I wish I could say that. But nooo - the nightmare of every javascript developer
rears its ugly head again...

Internet Explorer

Internet Explorer, also known as IE, also known as the Beast, again manages to mess things up. They don't support the onload event
for iframe. So the code...

document.getElementById("upload_target").onload = uploadDone;

will not work. WILL. NOT. WORK. Thanks IE, thanks very much.

So, what do we do? We use a small hack. We put a script tag inside the iframe with a onload event that calls the uploadDone() of the top frame. So now the server side script looks like this...

<html>
<head>
<script type="text/javascript">
function init() {
	if(top.uploadDone) top.uploadDone(); //top means parent frame.
}
window.onload=init;
</script>
<body>
<?php
list($name,$result) = upload('file','image_uploads','jpg,jpeg,gif,png');
if($name) { // Upload Successful
	// Put the PHP content from the last code sample here here
}
?>
</body>
</html>

Okay - now we have a IE-proof working system. Upload an image using the below demo application to see it in action.

If you have a better way of doing this, please, PLEASE let me know. I feel dirty doing it this way.

See it in Action

 

时间: 2024-08-03 23:15:11

Ajax File Upload Response Handling的相关文章

Ajax File Upload

Ajax File Upload You might have seen Ajax File Uploading in some sites. The basic idea is to upload a file without refreshing the page. Some sites go even further by providing details on how much percentage is uploaded, etc. It is very easy to achiev

jQuery Ajax File Upload实例源码_jquery

本文实例为大家分享了jQuery Ajax File Upload实例源码,供大家参考,具体内容如下 项目结构 Default.aspx Upload.aspx Scripts/- style.css 效果图   客户端html代码 <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="UploadFile.aspx.vb" Inherits="Web.UploadF

IE 8中jquery file upload 上传图片没反应

问题描述 IE 8中jquery file upload 上传图片没反应 jquery file upload 组件在chrome中好使 在IE中愣是没反应,前台的请求发送不到后台Controller中 后台SpringMVC 接受请求如下 @RequestMapping(value = "/fileupload", method = RequestMethod.POST) public @ResponseBody HBaseFileInfo upload(HttpServletReq

不用common file upload、struts 什么的,java文件上传功能怎么实现?

问题描述 不用common file upload.struts 什么的,java文件上传功能怎么实现? 不用common file upload.struts 什么的,java文件上传功能怎么实现,就单纯的用html和java实现文件上传? 解决方案 http://wangwei2008224078.blog.163.com/blog/static/214338275201342110555388/ 这个什么也没用,你可以参考 解决方案二: 用servlet的request获取文件流 解决方案

jQuery File Upload文件上传插件使用详解_jquery

jQuery File Upload 是一个Jquery文件上传组件,支持多文件上传.取消.删除,上传前缩略图预览.列表显示图片大小,支持上传进度条显示:支持各种动态语言开发的服务器端. 官网链接:https://github.com/blueimp/jQuery-File-Upload/wiki 特点:拖放支持:上传进度条:图像预览:可定制和可扩展的:兼容任何服务器端应用平台(PHP, Python, Ruby on Rails, Java, Node.js, Go etc.). 使用方法:

关于Ajax中通过response在后台传递数据问题

这是js代码: var System = { getHttpRequest: function(url, callback, options) { if (url.length < 0) return; var option = { url: url, type: "get", dataType: "json", cache: false, timeout: 30000, beforeSend: function(XHR) { }, complete: fun

用jQuery File Upload实现简单的文件上传

FORM中的代码: {# file_path #} <div class="form-group"> <label class="control-label col-md-3"> {{ form.file_path.label_tag }} {% for error in form.file_path.errors %} <span class="label label-danger">{{ error }}&

java Servlet与 Ajax显示上传文件进度

网页显示文件上传进度问题的分析: 显示上传进度的前提是获得上传的进度信息.我们可以想到的就是监听器,同时这有可以分两种情况:监听器可以放服务端,也可以放客户端. 下面的方法,其实更多的关键是前端,后端的话,可以用其他语言处理. 下面是对几种方法的总结: ##demo1 这种方式的服务端 使用commons FileUpload库的 ProgressListener 来监控进度,也就说进度情况是保存在服务端的,如果客户端想要知道进度,需要再次发起请求. 如果客户端想在一个页面完成,可以调用js到服

一个简单的ajax上传进度显示示例

本例用了jquery.form.js请到演示页面查看   CSS Code 复制代码 代码如下: <style> form { display: block; margin: 20px auto; background: #eee; border-radius: 10px; padding: 15px } #progress { position:relative; width:400px; border: 1px solid #ddd; padding: 1px; border-radius