Nodejs+HTML5兼容IE789的大文件上传完整版

业余将大文件上传重新梳理了一遍,后端基于Nodejs;有几个要点感觉很好玩:

  • 兼容性:IE789为代表;
  • 跨域上传:document.domain||middlePage;
  • 多文件上传:input[‘type=file‘] multiple;
  • 拖拽上传:drag drop;
  • 大文件分段:files.slice(s,e);
  • 断点续传:localStorage;
  • 接收分段的文件:formidable.onPart;
  • 陆续写入分段文件:fs.write(fd,bf,offset,length,position,cb);

很明显,重点都跟老旧IE没关系,在此也不打算用flash补充了,直接用最原始的做法:input[‘type=file‘]+hideFrame;所以,任务重心也就是HTML5了,坑并不多,因为所有知识点百度都能得到;可是事实告诉我,实际是与理论有差距的,特别是一些知识点还要缠在一起的时候,可能百度只是做到了授人以鱼,而要学会渔,还得自个儿折腾;

接着:

一步一步到现在。。。

1、对于低版本的IE789

说到要兼容IE78,顿时感觉自个儿这个小前端太苦逼,仅仅为了两个微软不要的浏览器,还要专门弄一堆乱七八糟hack,尼玛,有时为了兼容的代码,比原本的代码还多好多,有木有。。。好吧,原谅我,今天的天气确实挺燥热的;国情使然嘛,特殊项目还是得特殊对待,所以对于IE低版本,只求能上传,基本样子在那就行了;別犟了!

2、跨域上传

如果上传的程序是独立的站点或在静态资源站,那就要处理跨域问题了;一般较多的做法就是document.domain;另外还有一种采用middlePage的做法,我更喜欢后者;如果是要跨域的话,就得使用iframe引用那个上传文件;只需要在src上带上middlePage的整个路径,同时middlePage位于调用站而且也是一个影藏的iframe,文件上传完毕后把datas作为参数重新赋值到middlePage这个iframe上,然后在middlePage里调用callback;即可解决跨域问题;

例如在3000端口的站点调用端口为5000的站点里的上传,iframe的src:

1 http://localhost:5000/uploader?setDomainPath=http://localhost:5000/middlePage.html

middlePage里的回调:

1 window.parent.parent.callback(JSON.parse(utils.url.query.datas));

然后调用站的callback即可拿到datas;

3、多文件上传

多文件上传只需在input[‘type=file‘]加上multiple属性(同样是HTML5里新增的)即可,好吧,其实大家都知道的;重点在与拖拽上传的纠葛上;

4、拖拽上传

好吧,拖拽上传也就那样,dragenter、dragover、dragleave、drop就over了;接着上面:重点在于与多文件上传的纠葛上;一是multiple的多文件上传是input的change事件触发;另外拖拽的上传由drop触发;多个文件我是一个上传完毕后紧接着下一个开始;OK,问题来了,我先用change上传几个文件,然后再拖一批文件上传,还有单个文件可以取消或者删除,多次反复拖拽后,是不是顿时感觉绕到一起了;所以问题是否简单,不在于问题本身,而在于问题涉及到的其他问题以及你看待问题的角度和处理问题的能力;

因为多文件上传需要创建多条显示信息,每条上面绑两个值,一个是data-index,每个待上传文件的索引值,一个status,默认为0,上传成功后改为1;files本身为一个类数组的对象,它的索引可以与data-index对应,从data-index=0开始上传,完毕后寻找第一个status=0的item所对应的data-index是否存在,存在就上传这个,不存在即全部上传完了;但是onchange和drop的上传反复合到一起后,问题就来了,维护一个files远远不够;也就是,多种情况的files得合并,加上之前说的从哪开始上传由status=0对应的data-index决定的,所以合并files,也就是将files这个类数组对象转换为数组,然后多次操作合并他们,这样,就只需要维护这个合并后的数组即可;至于可能会删除某条,只需删掉其DOM,是否删掉文件,暂未处理,同时要保证这个合并后的数组的完整性,因为删掉之后可能还会再拖一批上传,保证data-index与合并后的数组的索引一一对应;这样拖拽与multiple的纠葛就化解了;

 1 var filesArr=null;
 2 var startFile=function(files) {
 3     var ff=$(‘.prograssInfo[status=0]‘).first();
 4     var ins=ff.attr(‘data-index‘);
 5     if (ins&&window.dropedCouldStart) {
 6         ff.find(‘.delthis‘).hide();
 7         var Files=new utils.Files({
 8             files:files[ins],
 9             chunkSize:10*1024*1024,
10             fieldIndex:ins,
11             onprogress:function(p){
12                 window.dropedCouldStart=false;
13                 callbk(p,ins);
14                 if(p>=100){
15                     window.dropedCouldStart=true;
16                     $(‘.prograssInfo[data-index=‘+ins+‘]‘)
17                     .attr(‘status‘,1).find(‘.delthis‘).show();
18                     startFile(filesArr);
19                     //确保files对象为最新合并后的
20                 }
21             }
22         });
23         Files.postFiles();
24     }
25 }
26
27 var dropCount=0;
28 var createField=function (files) {
29     if (files) {
30         var _filesArr=[].slice.call(files,0);
31         var _files=[];//过滤type size
32         for(var i=0;i<_filesArr.length;i++){
33             var _name=_filesArr[i].name;
34             if(_filesArr[i].size>maxFileSize||
35                 $.inArray(_name.substr(_name.lastIndexOf(‘.‘)+1).toLowerCase(),accept)!=-1){
36                 _files.push(_filesArr[i]);
37             };
38         }
39         if (filesArr&&filesArr.length) {
40             filesArr=filesArr.concat(_files);
41         }else{
42             filesArr=_files;
43         }
44         for (var i = filesArr.length-_files.length; i < filesArr.length; i++) {
45             $(contID)
46             .append(fieldItem(i,filesArr[i].name,utils.format.fileSize(filesArr[i].size)));
47             //data-index对应i的值,确保删除一条后index还能一一对应
48         }
49         if (window.dropedCouldStart==true&&filesArr&&filesArr.length) {
50             $(‘#uploadBtn‘).hide();
51             startFile(filesArr);
52         }
53     }
54 }

5、分段与断点续传

参考之前的:基于Nodejs的大文件上传之断点续传

6、分段接收与陆续写入

参考之前的:扒一扒Nodejs formidable的onPart

7、后端是Nodejs,就会那么一点,不献丑了;关于文件上传,网上成型的也是一大把,作为我前端路上必备的一大组件,我想自己实践一把,肯定感觉不一样,因为不管自己实现的还是网上的代码量都并不少,这其中的细节处理以及兼容问题,还有对HTML5的应用,对我都是挺有挑战意义的,当然,重点还是基础的积累,别人写的,拿过来用的是挺简单的,但是就前端而言,对于技术点的应用,你并不太理解,对应后端的处理,更是很难知道人家做了什么;所以,这样慢慢的肯定限制了你对前端技术点的扩展;

8、实测地址:http://images.famanoder.com/uploader?show=1

苦逼前端弄的破服务器,大家别往死里测啊!周末再梳理下,就会关闭这个地址的;

事实证明挺有搞头的,加油!

时间: 2024-08-25 00:27:19

Nodejs+HTML5兼容IE789的大文件上传完整版的相关文章

基于Nodejs的大文件上传之断点续传

接着<扒一扒Nodejs formidable的onPart>和<也说文件上传之兼容IE789的进度条---丢掉flash>:前面已完成兼容IE789的大文件上传:无flash的低版本进度条,高版本的分段上传,并已为断点续传做好铺垫: 说什么做好铺垫,原本以为Nodejs端已没问题,只剩前端依靠HTML5接着监听abort事件,保存中断时上传到第几块了(断点续传只支持文件比较大,然后意外上传中断了,暂时定50M开启断点续传吧),通过文件内容hash和该文件唯一上传token来记录断

BootStrap Progressbar 实现大文件上传的进度条

1.首先实现大文件上传,如果是几兆或者几十兆的文件就用基本的上传方式就可以了,但是如果是大文件上传的话最好是用分片上传的方式.我这里主要是使用在客户端进行分片读取到服务器段,然后保存,到了服务器段读取完了之后将分片数据进行组合. 2.前端代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UploadTest2.aspx.cs" Inherits="Htm

java实现大文件上传

文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用HTML5的API,对文件上传进行渐进式增强: * iframe上传 * ajax上传 * 进度条 * 文件预览 * 拖放上传 1.1 传统形式 文件上传的传统形式,是使用表单元素file,参考 http://www.ruanyifeng.com/blog/2012/08/file_upload.h

java+web+大文件上传下载

文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用HTML5的API,对文件上传进行渐进式增强:     * iframe上传  * ajax上传  * 进度条  * 文件预览  * 拖放上传 1.1 传统形式 文件上传的传统形式,是使用表单元素file,参考 http://www.ruanyifeng.com/blog/2012/08/file_

面试官:请你实现一个大文件上传和断点续传

前言这段时间面试官都挺忙的,频频出现在博客文章标题,虽然我不是特别想蹭热度,但是实在想不到好的标题了-.-,蹭蹭就蹭蹭 :) 事实上我在面试的时候确实被问到了这个问题,而且是一道在线 coding 的编程题,当时虽然思路正确,可惜最终也并不算完全答对 结束后花了一段时间整理了下思路,那么究竟该如何实现一个大文件上传,以及在上传中如何实现断点续传的功能呢? 本文将从零搭建前端和服务端,实现一个大文件上传和断点续传的 demo 文章有误解的地方,欢迎指出,将在第一时间改正,有更好的实现方式希望留下你

【原创】用JAVA实现大文件上传及显示进度信息

用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 一. 大文件上传基础描述: 各种WEB框架中,对于浏览器上传文件的请求,都有自己的处理对象负责对Http MultiPart协议内容进行解析,并供开发人员调用请求的表单内容. 比如: Spring 框架中使用类似CommonsMultipartFile对象处理表二进制文件信息. 而.NET 中使用HtmlInputFile/ HttpPostedFile对象处理二进制文件信息. 优点:使用框架内置对象可以很方便的

Socket大文件上传

1 public sealed class SocketData 2 { 3 private SocketData() 4 { 5 } 6 7 public static SendFileMode SendFile(Socket socket, string fileName, int maxBufferLength) 8 { 9 SendFileMode flag = SendFileMode.Success; 10 try 11 { 12 using (Stream fs = new Fil

IIS中的大文件上传问题解决方法

IIS出于安全考虑限制了大文件的上传,而网上百度到的大部分解决方法都是用一个管理员权限的记事本打开一个文件修改参数,但是我发现里面根本没有网上所说的那些参数,最后自己找到了修改发布文件的webconfig的方法解决的IIS对大文件上传的限制. 首先在system.web中加入以下代码 [csharp] view plain copy <httpRuntime maxRequestLength="2097151"//最大上传长度 useFullyQualifiedRedirectU

C# 大文件上传

IHttpModule 分块上传大文件 IHttpModule 分块上传大文件 来源:http://www.cnblogs.com/HeroBeast/archive/2008/03/18/1084874.html 1.一般的在Asp.net里上传文件都是10m左右,要做到大文件上传,必须要改web.config,不过改了web.config有时候也上传不成功,那是每次上传的文件太大,浏览器在这个过程中会超时,采用分块上传的方法就可以避免这种情况. 2.分块上传就是利用post的方法,把数据分块