老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′

言归正传。大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery File Uploader、FineUploader、Uploadify、Baidu Web Uploader 等等),功能都很强大,代码量一般也较大。当时心想,就这么个小功能,杀鸡焉用牛刀,用库的话还得熟悉它的用法,有的需要引入额外的库,纯Flash的不考虑,还是动手造个轮子得了,至少造过之后能知道底层的原理,关键是,自己写的东西,维护和修改方便,对过程可以进行全方位的控制。造个轮子简单,造个好用的轮子却就不是那么简单了。上传功能很快完成,但下次又用到的时候,却发现拿过来用需要修改不少东西,一是使用的JS库发生了变化,再就是UI界面完全不同,当时将上传逻辑和界面写的死死的,遇到不同的情况就需要针对性的改造。针对单一情况写的东西当然最轻量,只用考虑当前情况,不用的功能可以统统抛开,能做到最精简,但不方便重用。一个轮子如果不能重用,那当然不能算一个合格的轮子。意识到这点,而且既然已经走上了造轮子这条路,需要的核心功能也没有大的变化,那还是走下去吧。然后一路修修改改,最后完成了一个可用的版本。

v1.4版本已支持秒传+分片上传+断点续传(IE10+、其它标准浏览器),具体请参考Github代码。

关于我的上传控件

特点:

  • 轻量级,不依赖任何JS库,核心代码(Q.Uploader.js)仅约700行,min版本加起来不到12KB
  • 纯JS代码,无需Flash,无需更改后台代码即可实现带进度条(IE10+、其它标准浏览器)的上传,其它(eg:IE6+)自动降级为传统方式上传
  • 上传核心与UI界面分离,可以很方便的定制上传界面包括上传按钮
  • 上传文件的同时可以指定上传参数,支持上传类型过滤
  • 完善的事件回调,可针对上传的每个过程进行单独处理
  • 方便的UI接口,上传界面可以随心所欲的定制

简单调用示例(暴露的全局对象为Q):

var uploader = new Q.Uploader({
url: "api/upload.ashx?type=file",
target: document.getElementById("upload-target"),
view: document.getElementById("upload-view"), //html5: true, //是否启用html5上传,默认为true
//multiple: true, //是否允许多选(仅html5模式有效),默认为true
//auto: true, //添加任务后是否立即上传,默认为true //允许或不允许上传的文件类型 (allows 与 disallows 可单一或组合使用)
//allows: ".txt,.jpg,.png,.gif,.zip,.rar,.7z",
//disallows:".exe" //每次上传都会发送的参数(POST方式)
data: { user: "Devin" }
});

详细见示例代码或 Github(感觉逼格瞬间提升了有木有,*^_^* ),示例代码和源码在文章末尾

https://github.com/devin87/web-uploader

原理

1. html5上传

这个需要浏览器支持,无论是html5上传还是和html4上传,html上传控件都是必不可少的,即:

<input type="file">
//监听 input 的 change 事件,获取要上传的数据
input.onchange = function () {
//input.files 属性需要浏览器支持
var files = this.files; for (var i = 0, len = files.length; i < len; i++) {
var file = files[i]; //file.name || file.fileName => 文件名称
//file.size || file.fileSize => 文件大小 upload_html5(file);
}
};
//html5 上传
var xhr = new XMLHttpRequest(); //上传进度事件
xhr.upload.addEventListener("progress", function (e) { }, false);
//上传完成(成功)事件
xhr.addEventListener("load", function (e) {
//获取服务器响应
var text = e.target.responseText;
}, false);
//上传失败事件
xhr.addEventListener("error", function (e) { }, false);
//上传中断(取消)事件
xhr.addEventListener("abort", function (e) { }, false); var fd = new FormData;
//添加要上传的文件对象
fd.append("file", file);

xhr.open("POST", "api/upload.ashx");
xhr.send(fd);

2. html4上传(传统上传)

通过将 form 的 target 指向 iframe 的 name 来实现无刷新上传

<iframe name="html4-upload-target"></iframe>
<form action="api/upload.ashx" method="post" enctype="multipart/form-data" target="html4-upload-target">
<input type="file" name="upfile" />
</form>
//iframe load 事件
//注意:低版本 ie 支持 iframe 的 onload 事件,不过是隐形的(iframe.onload 方式绑定的将不会触发),需要通过 attachEvent 来注册
function bind_iframe_load(iframe, fn) {
if (iframe.attachEvent) iframe.attachEvent("onload", fn);
else iframe.addEventListener("load", fn, false);
} //html4上传完成回调
bind_iframe_load(iframe, function () {
//获取服务器响应
var text = iframe.contentWindow.document.body.innerHTML;
});

美化

上传按钮很丑,我想美化咋整?IE10+及标准浏览器支持 input.click() 触发文件选择,有人说,低版本IE也能弹出这个框框呀,这里有个坑,弹是能弹,但是可能基于安全考虑无法获取文件数据,报拒绝访问。

既然必须点击上传控件来选取文件,那么可以通过绝对定位让上传控件遮盖上传按钮,然后将上传控件透明度设为0,以达到隐身的效果,如此一来表面点击的是上传按钮,实际点击的是上传控件,问题也就随之解决。

<!-- 上传按钮,样式随自己控制,假设宽高为分别为120px,36px,相对于body的边距分别为100px,100px -->
<a class="upload-target">选择文件上传</a> <!-- 上传控件,选择文件后(change事件)将 input 追加到 form 即可 -->
<div style="width:120px;height:36px;position:absolute;left:100px;top:100px;overflow:hidden;filter: alpha(opacity=0);opacity:0;">
<input type="file" name="upfile" style="width:120px;height:36px;font-size:100px;" />
</div>

关于html4上传,刚好看到一篇 利用iframe无刷新上传文件的坑 文章,有兴趣的童鞋可以看看。

拖拽文件上传

文件拖拽利用了 HTML5 中的 Drag and Drop 特性,可以直接将本地电脑上的文件拖拽到网页中。

1. 定义拖拽区域

<div id="drop-area">将文件拖拽到此区域</div>

2. 获取拖拽数据并上传

var boxDropArea = $("#drop-area")[0];

//TODO:检测支持情况

//阻止浏览器默认拖放行为
$(boxDropArea).on("dragleave dragenter drop dragover", function (e) {
e.preventDefault();
e.stopPropagation();
}); //获取拖拽的文件对象并上传
$(boxDropArea).on("drop", function (e) {
var files = e.dataTransfer.files;
if (!files || files.length == 0) return; for (var file in files) {
//TODO:上传文件
upload(file);
}
});

想了解更多拖拽的信息,可以参考这篇文章 HTML5 drag & drop 拖拽与拖放简介

代码下载

asp.net 或其它后台示例代码

Node.js 示例代码

写在最后

如果本文或本项目对您有帮助的话,请不吝点个赞。欢迎交流!

打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器的更多相关文章

  1. H5实现多图片预览上传,可点击可拖拽控件介绍

    版权声明:欢迎转载,请注明出处:http://blog.csdn.net/weixin_36380516 在做图片上传时发现一个蛮好用的控件,支持多张图片同时上传,可以点击选择图片,也可以将图片拖拽到 ...

  2. HTML5 CSS3 经典案例:无插件拖拽上传图片 (支持预览与批量) (二)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/31513065 上一篇已经实现了这个项目的整体的HTML和CSS: HTML5 C ...

  3. 【手记】小心在where中使用NEWID()的大坑 【手记】解决启动SQL Server Management Studio 17时报Cannot find one of more components...的问题 【C#】组件分享:FormDragger窗体拖拽器 【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

    [手记]小心在where中使用NEWID()的大坑 这个表达式: ABS(CHECKSUM(NEWID())) % 3 --把GUID弄成正整数,然后取模 是随机返回0.1.2这三个数,不可能返回其它 ...

  4. 通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽

    前言 关于讲解 JS 的拖拽功能的文章数不胜数,我确实没有必要大费周章再写一篇重复的文章来吸引眼球.本文的重点是讲解如何在某些特定的元素上禁止拖拽.这是我在编写插件时遇到的问题,其实很多插件的拖拽功能 ...

  5. Retrofit2文件上传下载及其进度显示

    序 前面一篇文章介绍了Retrofit2的基本使用,这篇文章接着介绍使用Retrofit2实现文件上传和文件下载,以及上传下载过程中如何实现进度的显示. 文件上传 定义接口 1 2 3 @Multip ...

  6. .net core版 文件上传/ 支持批量上传,拖拽以及预览,bootstrap fileinput上传文件

    asp.net mvc请移步 mvc文件上传支持批量上传,拖拽以及预览,文件内容校验 本篇内容主要解决.net core中文件上传的问题  开发环境:ubuntu+vscode 1.导入所需要的包:n ...

  7. vue-drag-resize 可拖拽可缩放的标签,如何管理多个拖拽元素之间的zIndex?操作上需要保持当前激活的组件是最上层,但是在总体上,又要确保其图层管理的顺序。

    麻烦总是不断出现,还好办法总比困难多, 1.公司开发一款可视化编辑html网页的多媒体编辑平台,牵扯到标签元素的拖拽,缩放,我找了找方法发现原生技术实现起来代码太多,麻烦,还好找到了一个vue组件,可 ...

  8. 【C#】组件分享:FormDragger-窗体拖拽器

    适用:.net2.0+ winform项目 介绍: 类似QQ.迅雷等讲究UI体验的软件,都支持在窗口内多处地方拖动窗口,而不必老实巴交的去顶部标题栏拖,这个组件就是让winform也能这样随性拖拽,随 ...

  9. 【C#】组件分享:FormDragger窗体拖拽器

    适用:.net2.0+ winform项目 介绍: 类似QQ.迅雷等讲究UI体验的软件,都支持在窗口内多处地方拖动窗口,而不必老实巴交的去顶部标题栏拖,这个组件就是让winform也能这样随性拖拽,随 ...

随机推荐

  1. Mysql字符类型比较

    一. binary和char比较: binary 字节为单位,char字符为单位,字符占几个字节取决于字符集 binary  比较规则基于字节值,char基于字符,即使是_bin的比较规则 范围都0- ...

  2. unity3d中检测一个物体是否在摄像机视野范围内

    这个脚本最好是把模型对象的锚点设置在最低点.好了直接上脚本.可以直接复制代码,把CS文件拖到一个Camera上,然后把目标拖到targetTran中去就行了. using UnityEngine; u ...

  3. 转 LoadRunner 技巧之 IP欺骗 (推荐)

    IP欺骗也是也loadrunner自带的一个非常有用的功能. 需要使用ip欺骗的原因: 1.当某个IP的访问过于频繁,或者访问量过大是,服务器会拒绝访问请求,这时候通过IP欺骗可以增加访问频率和访问量 ...

  4. HTTP权威协议笔记-6.代理

    6.1 Web的中间实体 Http的代理服务器即是客户端的服务器又是服务器的客户端. 它介于服务器与客户端之间,当客户端发送请求报文经过它时,它会像服务器一样正确的处理请求和返回响应,同时,代理服务器 ...

  5. MapReduce 过程分析

    原文地址:http://blog.jobbole.com/81676/ 2.WordCount处理过程 上面给出了WordCount的设计思路和源码,但是没有深入细节,下面对WordCount进行更加 ...

  6. Go Data Structures: Interfaces

    refer:http://research.swtch.com/interfaces Go Data Structures: Interfaces Posted on Tuesday, Decembe ...

  7. SQL初级语法 [查询: SELECT]

    SQL查询: SELECT 普通查询: SELECT "栏位名" FROM "表格名" DISTINCT 查询:(去掉重复) SELECT DISTINCT & ...

  8. 照片灰蒙蒙?用PS的曲线功能来解决 (转)

    原文地址:http://realjasonc.blog.163.com/blog/static/16475932520107594048957/ 上次,给大家看了几张较为典型的直方图.其实直方图的状态 ...

  9. Loadrunner ---集合点设置

    测试场景,实现用户登录的200并发: 1.录制登录退出脚本,且登录退出放aciton中 2.在登录的地方设置集合点 设置集合点有如下4中方式: 1)在要插入集合点的地方,右击鼠标按如下图操作:

  10. LoadRunner ---协议分析

    在做性能测试的时候,协议分析是困扰初学者的难题,选择错误的协议会导致Virtual User Generator 录制不到脚本:或录制的脚本不完整,有些应用可能需要选择多个协议才能完整的记录 客户端与 ...