一、
通过iframe来实现无刷新的的文件上传,其实是有刷新的,只是在iframe里面隐藏了而已
简单的原理说明:
<form id="form1" method="post" action="upload.do" enctype="multipart/form-data" target="uploadframe" >
<input type="file" id="upload" name="文件上传" />
</form>
<iframe id="uploadframe" name="result_frame" style="visibility:hidden;"></iframe>
form里面的target要与iframe里面的id的值相等,指示是form相应了post事件,也就是post时间相应的时候刷新的是iframe而不是整个页面。
二、
利用jQuery的插件AjaxFileUpload 可以简单地实现这个异步的上传的效果 插件地址: http://www.phpletter.com/Our-Projects/AjaxFileUpload/
<script type="text/javascript" language="javascript" src="js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="js/ajaxfileupload.js"></script>


{
$( " #loading " )
.ajaxStart( function (){
$( this ).show();
})
.ajaxComplete( function (){
$( this ).hide();
});
$.ajaxFileUpload
(
{
url: ' Upload.ashx ' ,
secureuri: false ,
fileElementId: ' fileToUpload ' ,
dataType: ' json ' ,
success: function (data, status)
{
if ( typeof (data.error) != ' undefined ' )
{
if (data.error != '' )
{
alert(data.error);
} else
{
alert(data.msg);
}
}
},
error: function (data, status, e)
{
alert(e);
}
}
)
return false ;
}
<input id="fileToUpload" type="file" size="45" name="fileToUpload">
<input type="button" id="buttonUpload" onclick="return ajaxFileUpload();">
上传</input>
Upload.ashx


{
HttpPostedFile file = Request.Files[ 0 ];
string msg = "" ;
string error = "" ;
if (file.ContentLength == 0 )
error = " 文件长度为0 " ;
else
{
file.SaveAs(Server.MapPath( " file " ) + " \\ " + Path.GetFileName(file.FileName));
msg = " 上传成功 " ;
}
string result = " { error:' " + error + " ', msg:' " + msg + " '} " ;
Response.Write(result);
Response.End();
}
PS:ajaxfileupload.js代码


createUploadIframe: function (id, uri)
{
// create frame
var frameId = ' jUploadFrame ' + id;
if (window.ActiveXObject) {
var io = document.createElement( ' <iframe id=" ' + frameId + ' " name=" ' + frameId + ' " /> ' );
if ( typeof uri == ' boolean ' ){
io.src = ' javascript:false ' ;
}
else if ( typeof uri == ' string ' ){
io.src = uri;
}
}
else {
var io = document.createElement( ' iframe ' );
io.id = frameId;
io.name = frameId;
}
io.style.position = ' absolute ' ;
io.style.top = ' -1000px ' ;
io.style.left = ' -1000px ' ;
document.body.appendChild(io);
return io
},
createUploadForm: function (id, fileElementId)
{
// create form
var formId = ' jUploadForm ' + id;
var fileId = ' jUploadFile ' + id;
var form = $( ' <form action="" method="POST" name=" ' + formId + ' " id=" ' + formId + ' " enctype="multipart/form-data"></form> ' );
var oldElement = $( ' # ' + fileElementId);
var newElement = $(oldElement).clone();
$(oldElement).attr( ' id ' , fileId);
$(oldElement).before(newElement);
$(oldElement).appendTo(form);
// set attributes
$(form).css( ' position ' , ' absolute ' );
$(form).css( ' top ' , ' -1200px ' );
$(form).css( ' left ' , ' -1200px ' );
$(form).appendTo( ' body ' );
return form;
},
ajaxFileUpload: function (s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var form = jQuery.createUploadForm(id, s.fileElementId);
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = ' jUploadFrame ' + id;
var formId = ' jUploadForm ' + id;
// Watch for a new set of requests
if ( s.global && ! jQuery.active ++ )
{
jQuery.event.trigger( " ajaxStart " );
}
var requestDone = false ;
// Create the request object
var xml = {}
if ( s.global )
jQuery.event.trigger( " ajaxSend " , [xml, s]);
// Wait for a response to come back
var uploadCallback = function (isTimeout)
{
var io = document.getElementById(frameId);
try
{
if (io.contentWindow)
{
xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML: null ;
xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument:io.contentWindow.document;
} else if (io.contentDocument)
{
xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML: null ;
xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument:io.contentDocument.document;
}
} catch (e)
{
jQuery.handleError(s, xml, null , e);
}
if ( xml || isTimeout == " timeout " )
{
requestDone = true ;
var status;
try {
status = isTimeout != " timeout " ? " success " : " error " ;
// Make sure that the request was successful or notmodified
if ( status != " error " )
{
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData( xml, s.dataType );
// If a local callback was specified, fire it and pass it the data
if ( s.success )
s.success( data, status );
// Fire the global callback
if ( s.global )
jQuery.event.trigger( " ajaxSuccess " , [xml, s] );
} else
jQuery.handleError(s, xml, status);
} catch (e)
{
status = " error " ;
jQuery.handleError(s, xml, status, e);
}
// The request was completed
if ( s.global )
jQuery.event.trigger( " ajaxComplete " , [xml, s] );
// Handle the global AJAX counter
if ( s.global && ! -- jQuery.active )
jQuery.event.trigger( " ajaxStop " );
// Process result
if ( s.complete )
s.complete(xml, status);
jQuery(io).unbind()
setTimeout( function ()
{ try
{
$(io).remove();
$(form).remove();
} catch (e)
{
jQuery.handleError(s, xml, null , e);
}
}, 100 )
xml = null
}
}
// Timeout checker
if ( s.timeout > 0 )
{
setTimeout( function (){
// Check to see if the request is still happening
if ( ! requestDone ) uploadCallback( " timeout " );
}, s.timeout);
}
try
{
// var io = $('#' + frameId);
var form = $( ' # ' + formId);
$(form).attr( ' action ' , s.url);
$(form).attr( ' method ' , ' POST ' );
$(form).attr( ' target ' , frameId);
if (form.encoding)
{
form.encoding = ' multipart/form-data ' ;
}
else
{
form.enctype = ' multipart/form-data ' ;
}
$(form).submit();
} catch (e)
{
jQuery.handleError(s, xml, null , e);
}
if (window.attachEvent){
document.getElementById(frameId).attachEvent( ' onload ' , uploadCallback);
}
else {
document.getElementById(frameId).addEventListener( ' load ' , uploadCallback, false );
}
return {abort: function () {}};
},
uploadHttpData: function ( r, type ) {
var data = ! type;
data = type == " xml " || data ? r.responseXML : r.responseText;
// If the type is "script", eval it in global context
if ( type == " script " )
jQuery.globalEval( data );
// Get the JavaScript object, if JSON is used.
if ( type == " json " )
eval( " data = " + data );
// evaluate scripts within html
if ( type == " html " )
jQuery( " <div> " ).html(data).evalScripts();
// alert($('param', data).each(function(){alert($(this).attr('value'));}));
return data;
}
})
三、纯iframe实现上传
upload.ashx


using System;
using System.Web;
public class upload : IHttpHandler {
private string Js( string v) { // 此函数进行js的转义替换的,防止字符串中输入了'后造成回调输出的js中字符串不闭合
if (v == null ) return "" ;
return v.Replace( " ' " , @" \' " );
}
// 下面就是一个简单的示例,保存上传的文件,如果要验证上传的后缀名,得自己写,还有写数据库什么的
public void ProcessRequest (HttpContext context) {
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
HttpServerUtility Server = context.Server;
// 指定输出头和编码
Response.ContentType = " text/html " ;
Response.Charset = " utf-8 " ;
HttpPostedFile f = Request.Files[ " upfile " ]; // 获取上传的文件
string des = Request.Form[ " des " ] // 获取描述
,newFileName = Guid.NewGuid().ToString(); // 使用guid生成新文件名
if (f.FileName == "" ) // 未上传文件
Response.Write( " <script>parent.UpdateMsg('','');</script> " ); // 输出js,使用parent对象得到父页的引用
else { // 保存文件
newFileName += System.IO.Path.GetExtension(f.FileName); // 注意加上扩展名
try {
f.SaveAs(Server.MapPath( " ~/uploads/ " + newFileName)); // 如果要保存到其他地方,注意修改这里
// 调用父过程更新内容,注意要对des变量进行js转义替换,防止字符串不闭合提示错误
Response.Write( " <script>parent.UpdateMsg(' " + Js(des) + " ',' " + newFileName + " ')</script> " );
}
catch {
Response.Write( " <script>alert('保存文件失败!\\n请检查文件夹是否有写入权限!');</script> " ); // 如果保存失败,输出js提示保存失败
}
}
}
public bool IsReusable {
get {
return false ;
}
}
}
test.htm


< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv ="content-type" content ="text/html;charset=utf-8" />
< title > 使用隐藏的Iframe实现ajax无刷新上传 </ title >
</ head >
< body >
< script type ="text/javascript" >
function UpdateMsg(des,filename){ // 此函数用来提供给提交到的页面如upload.ashx输出js的回调,更新当前页面的信息
if (filename == '' ){alert( ' 未上传文件! ' ); return false ;}
document.getElementById( ' ajaxMsg ' ).innerHTML = ' 你在表单中输入的“文件描述”为: ' + des + ' <br/> '
+ ' 上传的图片为:<a href="uploads/ ' + filename + ' " target="_blank"> ' + filename + ' </a> ' ;
}
function check(f){
if (f.des.value == '' ){
alert( ' 请输入文件描述! ' );f.des.focus(); return false ;
}
if (f.upfile.value == '' ){
alert( ' 请选择文件! ' );f.upfile.focus(); return false ;
}
}
</ script >
<!-- 隐藏的iframe来接受表单提交的信息 -->
< iframe name ="ajaxifr" style ="display:none;" ></ iframe >
<!-- 这里设置target="ajaxifr",这样表单就提交到iframe里面了,和平时未设置target属性时默认提交到当前页面 -->
<!-- 注意一点的是使用iframe时在提交到的页面可以直接输出js来操作父页面的信息,一般的ajax提交文本信息时你需要返回信息,如果是js信息你还得eval下 -->
< form method ="post" enctype ="multipart/form-data" action ="upload.ashx" target ="ajaxifr" onsubmit ="return check(this)" >
文件描述: < input type ="text" name ="des" />< br >
选择文件: < input type ="file" name ="upfile" />< br >
< input type ="submit" value ="提交" />
</ form >
<!-- 放入此div用来实现上传的结果 -->
< div id ="ajaxMsg" ></ div >
</ body >
</ html >