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

言归正传。大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery File UploaderFineUploaderUploadifyBaidu 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. Python + PIL 处理支付宝AR红包

    思路比较简单:1.对图片进行锐化处理:2.设(r_h, g_h, b_h)为支付宝遮罩黑条的RGB值,以此为中心,查找半径为Diff_radius的范围内所有的色值: 3.对每一行符合步骤2的像素点个 ...

  2. How secure FB Messenger is?

    It's reported that FB Messenge is the most secure App for instant messaging service. Let's see if FB ...

  3. 采用UDP协议的PIC32MZ ethernet bootloader

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 经过千辛万苦,今天终于 ...

  4. weedfs getsockopt: connection timed out

    启动master weed master -ip 10.191.197.133 -mdir /namenode -ip.bind 10.191.197.133 I0809 16:53:51 7721 ...

  5. 43、哈工大NLP自然语言处理,LTP4j的测试+还是测试

    1.首先需要构建自然语言处理的LTP的框架 (1)需要下载LTP的源码包即c++程序(https://github.com/HIT-SCIR/ltp)下载完解压缩之后的文件为ltp-master (2 ...

  6. 转: windows下面安装Python和pip终极教程

    原文: http://www.cnblogs.com/yuanzm/p/4089856.html 因为如果是初学者在windows环境下安装,简直是折磨人,会遇到各种蛋疼的情况.本文希望提供傻瓜式的教 ...

  7. linux 驱动学习笔记04--简单驱动

    首先贴代码helloworld.c和Makefile /************************************************************************ ...

  8. JQuery 常用

    1.同一name分组的多个radio,获取选中radio的value值: var check_val=$("input[name='属性名']:checked").val(); 2 ...

  9. 什么时候该用NoSQL?

    : 杂谈   NoSQL这两年越来越热,尤其是大型互联网公司非常热衷这门技术.根据笔者的经验,并不是任何场景,NoSQL都要优于关系型数据库.下面我们来具体聊聊,什么时候使用NoSQL比较给力: 1) ...

  10. fedora 24下修改IP

    在ROOT环境下 cd /etc/sysconfig/network-scripts 找到类似  ifcfg-enp1s0的文件 sudo vi ifcfg-enp1s0 HWADDR=XX:XX:X ...