AjaxFileUpload需求

传统的form表单方式上传文件,  必然会刷新整个页面。 那么在不刷新界面的情况下实现文件的上传呢?

在 HTML4下, 聪明的程序员们发明了 ajax file upload 方式(form + hidden iframe方式), 为本文介绍的对象。

 在HTML5中XMLHttpRequest实现了异步上传文件(介绍见 http://wenzhixin.net.cn/2013/11/28/ajax_file_upload_html5)。

开源项目

官网为 https://github.com/davgothic/AjaxFileUpload

此插件支持, 选择文件后,  立刻上传文件, 整体页面不刷新,  并可以根据后台返回的json报给用户上传的状况。

使用说明

此插件是基于jquery库,  需要引用jquery库,

    <script type="text/javascript" src="jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="../jquery.ajaxfileupload.js"></script>

文件控件(使用此插件 form都不用  写):

    <form method="post" action="" enctype="multipart/form-data">
<label>File Input: <input type="file" name="file" id="demo1" /></label>
<div id="uploads"> </div>
</form>

使用此插件初始化控件:

    <script type="text/javascript">
$(document).ready(function() {
$("#demo1").AjaxFileUpload({
onComplete: function(filename, response) {
$("#uploads").append(
$("<img />").attr("src", filename).attr("width", 200)
);
}
});
});
</script>

后台实现PHP参考:

<?php
/**
* This is just an example of how a file could be processed from the
* upload script. It should be tailored to your own requirements.
*/
// Only accept files with these extensions
$whitelist = array('jpg', 'jpeg', 'png', 'gif');
$name = null;
$error = 'No file uploaded.';
if (isset($_FILES)) {
if (isset($_FILES['file'])) {
$tmp_name = $_FILES['file']['tmp_name'];
$name = basename($_FILES['file']['name']);
$error = $_FILES['file']['error']; if ($error === UPLOAD_ERR_OK) {
$extension = pathinfo($name, PATHINFO_EXTENSION);
if (!in_array($extension, $whitelist)) {
$error = 'Invalid file type uploaded.';
} else {
move_uploaded_file($tmp_name, $name);
}
}
}
}
echo json_encode(array(
'name' => $name,
'error' => $error,
));
die();

定制接口

四个定制接口, 可以定制内容包括:

1 上传url (定制自定义的 action)

2  提交submit事件 (例如对文件后缀校验不成功, 不上传)

3  选中文件change事件 (定制选中文件后的 等待进度条等)

4 提交完成后的响应事件 complete (提交成功后, 将提交结果添加到列表中)

    <form method="post" action="" enctype="multipart/form-data">
<label>File Input: <input type="file" name="file" id="demo1" /></label>
</form>
<script type="text/javascript" src="jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="../jquery.ajaxfileupload.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var interval;
function applyAjaxFileUpload(element) {
$(element).AjaxFileUpload({
action: "upload.php",
onChange: function(filename) {
// Create a span element to notify the user of an upload in progress
var $span = $("<span />")
.attr("class", $(this).attr("id"))
.text("Uploading")
.insertAfter($(this));
$(this).remove();
interval = window.setInterval(function() {
var text = $span.text();
if (text.length < 13) {
$span.text(text + ".");
} else {
$span.text("Uploading");
}
}, 200);
},
onSubmit: function(filename) {
// Return false here to cancel the upload
/*var $fileInput = $("<input />")
.attr({
type: "file",
name: $(this).attr("name"),
id: $(this).attr("id")
});
$("span." + $(this).attr("id")).replaceWith($fileInput);
applyAjaxFileUpload($fileInput);
return false;*/
// Return key-value pair to be sent along with the file
return true;
},
onComplete: function(filename, response) {
window.clearInterval(interval);
var $span = $("span." + $(this).attr("id")).text(filename + " "),
$fileInput = $("<input />")
.attr({
type: "file",
name: $(this).attr("name"),
id: $(this).attr("id")
});
if (typeof(response.error) === "string") {
$span.replaceWith($fileInput);
applyAjaxFileUpload($fileInput);
alert(response.error);
return;
}
$("<a />")
.attr("href", "#")
.text("x")
.bind("click", function(e) {
$span.replaceWith($fileInput);
applyAjaxFileUpload($fileInput);
})
.appendTo($span);
}
});
}
applyAjaxFileUpload("#demo1");
});
</script>

实现原理

参考下面文章的说明:

http://wenzhixin.net.cn/2013/11/27/ajax_file_upload_iframe

此处结合此开源项目的代码介绍下:

1、 应用 AjaxFileUpload 到 file控件后, 此file控件就绑定了 change事件, 事件函数为 onChange

        return this.each(function() {
var $this = $(this);
if ($this.is("input") && $this.attr("type") === "file") {
$this.bind("change", onChange);
}
});

2、 用户选择文件后, 触发 change事件, 调用 onChange 函数

此函数, 先克隆一个 file控件, 并将 此克隆控件,  也使用 AjaxFileUpload  初始化(即绑定了 onChange函数,地位与原始控件相同了),

     并将此控件 插入到 原始控件前。

                $clone   = $element.removeAttr('id').clone().attr('id', id).AjaxFileUpload(options),
。。。。。
            // We append a clone since the original input will be destroyed
            $clone.insertBefore($element);

后创建  隐藏的 iframe, 并初始化 iframe的 load事件(form提交后响应的框架), 事件函数即为 响应处理函数:

                iframe   = createIframe(),
。。。。 iframe.bind("load", {element: $clone, form: form, filename: filename}, onComplete);

后创建提交的form, 将form的提交事件绑定为onSubmit, 并做提交动作:

                form     = createForm(iframe);
。。。。。
form.append($element).bind("submit", {element: $clone, iframe: iframe, filename: filename}, onSubmit).submit();

3、 2步骤中form提交后, 文件上传成功, 在iframe的load事件被触发, 执行onComplete函数, 将执行结果进行处理, 处理完毕后将 onChange中创建的 form 和 iframe删除:

        function onComplete (e) {
var $iframe = $(e.target),
doc = ($iframe[0].contentWindow || $iframe[0].contentDocument).document,
response = doc.body.innerHTML; if (response) {
response = $.parseJSON(response);
} else {
response = {};
}
// 自定义的处理逻辑
settings.onComplete.call(e.data.element, e.data.filename, response); // Remove the temporary form and iframe
e.data.form.remove();
$iframe.remove();
}

change事件只生效一次说明

如果对 file 控件应用 ajaxfileupload 控件初始化后, 接着设置 一个附加的 change 事件, 在第一用户选择文件上传后, 会丢失, 是因为 文件控件被替换为clone体, 但是clone体没带有old event, 生效代码为 clone参数为空, 意味着浅拷贝:

        function onChange(e) {
var $element = $(e.target),
id = $element.attr('id'),
$clone = $element.removeAttr('id').clone().attr('id', id).AjaxFileUpload(options),
filename = $element.val().replace(/.*(\/|\\)/, ""),
iframe = createIframe(),
form = createForm(iframe); // We append a clone since the original input will be destroyed
$clone.insertBefore($element);

解决方法,使用代理:

$(document).on('change', '#upload', function() {

});

参考:

http://wenzhixin.net.cn/2013/11/26/jquery_file_upload_change_once

AjaxFileUpload 方法与原理分析的更多相关文章

  1. Android ListView实现不同item的方法和原理分析

    ListView实现不同item的方法和原理分析 一问题抛出Listview是android里面的重要组件,用来显示一个竖向列表,这个没有什么问题:但是有个时候列表里面的item不是一样的,如下图,列 ...

  2. Charles的HTTPS抓包方法及原理分析

    原文地址:http://www.jianshu.com/p/870451cb4eb0 背景 作为移动平台的RD,项目开发过程中一项比较重要的甩锅技能——抓包应该大家都比较熟悉了,毕竟有些bug可能是由 ...

  3. Eventbus 使用方法和原理分析

    对于 Eventbus ,相信很多 Android 小伙伴都用到过. 1.创建事件实体类 所谓的事件实体类,就是传递的事件,一个组件向另一个组件发送的信息可以储存在一个类中,该类就是一个事件,会被 E ...

  4. hashmap冲突的解决方法以及原理分析:

    在Java编程语言中,最基本的结构就是两种,一种是数组,一种是模拟指针(引用),所有的数据结构都可以用这两个基本结构构造,HashMap也一样.当程序试图将多个 key-value 放入 HashMa ...

  5. String类中intern方法的原理分析

    一,前言 ​ 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...

  6. jQuery的ready方法实现原理分析

    jQuery中的ready方法实现了当页面加载完成后才执行的效果,但他并不是window.onload或者doucment.onload的封装,而是使用 标准W3C浏览器DOM隐藏api和IE浏览器缺 ...

  7. Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题

    Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...

  8. HashMap底层原理分析(put、get方法)

    1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...

  9. String类原理分析及部分方法

    //String类原理分析及部分方法 //http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html //http://www.cnblo ...

随机推荐

  1. CSS雪碧,即CSS Sprite 简单的例子

    CSS Sprite生成工具 http://pan.baidu.com/s/1gdGQwiJ 工具可将多幅图片整合一张,并生成CSS. HTML代码 <style> .img{backgr ...

  2. 应用程序间跳转 (友盟SSO 授权 与系统自带的分享)

    应用程序间跳转的应用场景 使用第三方用户登录,如微信登录,返回用户名和密码 需要用户授权,返回到调用程序,同时返回授权的用户名 应用程序推广,跳转到itunes并显示指定app下载页 第三方支付,跳转 ...

  3. ACM: NBUT 1646 Internet of Lights and Switches - 二进制+map+vector

    NBUT 1646 Internet of Lights and Switches Time Limit:5000MS     Memory Limit:65535KB     64bit IO Fo ...

  4. 【BZOJ】1115: [POI2009]石子游戏Kam

    http://www.lydsy.com/JudgeOnline/problem.php?id=1115 题意:n堆石子,个数是从左到右单增.每一次可以从任意堆取出任意石子,但要保持单增这个性质.问先 ...

  5. UVA 10892 - LCM Cardinality(数学题)

    题目链接 写写,就ok了. #include <cstdio> #include <cstring> #include <string> #include < ...

  6. HDU 4722 Good Numbers(DP)

    题目链接 脑子有点乱,有的地方写错了,尚大婶鄙视了... 来个模版的. #include <iostream> #include <cstdio> #include <c ...

  7. 【BZOJ1270】1270: [BeijingWc2008]雷涛的小猫 DP

    Description   Input Output Sample Input Sample Output 8 HINT Source 唉这么蠢的Dp没一下子看出来,Dp真是太弱了啦. #includ ...

  8. C语言中if语句

    C语言if语句后面的表达式 C语言中if关键字之后(即括号内)均为表达式. 该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量,这些变量的值都换算成了逻辑 ...

  9. [转] 擎天哥as3教程系列第二回——性能优化

    所谓性能优化主要是让游戏loading和运行的时候不卡. 一  优化fla导出的swf的体积? 1,  在flash中,舞台上的元件最多,生成的swf越大,库里面有连接名的元件越多,swf越大.当舞台 ...

  10. 利用iframe将div放置在object的上面

    这两天在写一个用object上传照片的网页,在上传时,需要弹出一个进度条的div,我就按照正常的思维模式,将进度条div设为绝对定位,将其z-index设置的很大,结果,进度条div被object给遮 ...