jQuery webuploader分片上传大文件


Posted in Javascript onNovember 07, 2016

一般在做文件上传的时候,都是通过客户端把要上传的文件上传到服务器,此时上传的文件都在服务器内存,如果上传的是视频等大文件,那么服务器内存就很紧张,而且一般我们都是用flash或者html5做异步上传,如果文件比较大的话,即便是客户端显示文件已经上传了100%,还是会有一个比较长时间的等待,而且当前页面对服务器的请求也会被阻塞。

正常情况下,一般都是在长传完成后,在服务器直接保存。

public void ProcessRequest(HttpContext context)
  {
   context.Response.ContentType = "text/plain";
   //保存文件
   context.Request.Files[0].SaveAs(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName));
   context.Response.Write("Hello World");
  }

最近项目中用百度开源的上传组件webuploader,官方介绍webuploader支持分片上传。具体webuploader的使用方法见官网http://fex.baidu.com/webuploader/。

var uploader = WebUploader.create({
   auto: true,
   swf:'/webuploader/Uploader.swf',
   // 文件接收服务端。
   server: '/Uploader.ashx',
   // 内部根据当前运行是创建,可能是input元素,也可能是flash.
   pick: '#filePicker',
   chunked: true,//开启分片上传
   threads: 1,//上传并发数
   //由于Http的无状态特征,在往服务器发送数据过程传递一个进入当前页面是生成的GUID作为标示
   formData: {guid:"<%=Guid.NewGuid().ToString()%>"}
  });

webuploader的分片上传是把文件分成若干份,然后向你定义的文件接收端post数据,如果上传的文件大于分片的尺寸,就会进行分片,然后会在post的数据中添加两个form元素chunk和chunks,前者标示当前分片在上传分片中的顺序(从0开始),后者代表总分片数。

选择一个文件后分了7个分片,所以对Uploader.ashx进行了7次post数据的过程。

jQuery webuploader分片上传大文件

每次请求中的form元素chunk和chunks以及为了标示是同一个文件的分片的GUID

 jQuery webuploader分片上传大文件

在服务器端接收到数据后,就可以根据这些参数进行处理了。

1、按按GUID创建一个临时文件

2、把收到的分片数据追加到对应GUID的文件中。

3、根据上传的文件名重命名临时文件

4、如果没有分片直接保存

public void ProcessRequest(HttpContext context)
  {
   context.Response.ContentType = "text/plain";
   //如果进行了分片
   if (context.Request.Form.AllKeys.Any(m => m == "chunk"))
   {
    //取得chunk和chunks
    int chunk =Convert.ToInt32(context.Request.Form["chunk"]);
    int chunks = Convert.ToInt32(context.Request.Form["chunks"]);

    
    //根据GUID创建用该GUID命名的临时文件
    string path = context.Server.MapPath("~/1/" + context.Request["guid"]);
    FileStream addFile = new FileStream(path, FileMode.Append, FileAccess.Write);
    BinaryWriter AddWriter = new BinaryWriter(addFile);
    //获得上传的分片数据流
    HttpPostedFile file = context.Request.Files[0];
    Stream stream = file.InputStream;

    BinaryReader TempReader = new BinaryReader(stream);
    //将上传的分片追加到临时文件末尾
    AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
    //关闭BinaryReader文件阅读器
    TempReader.Close();
    stream.Close();
    AddWriter.Close();
    addFile.Close();

    TempReader.Dispose();
    stream.Dispose();
    AddWriter.Dispose();
    addFile.Dispose();
    //如果是最后一个分片,则重命名临时文件为上传的文件名
    if (chunk == (chunks - 1))
    {
     FileInfo fileinfo = new FileInfo(path);
     fileinfo.MoveTo(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName));
    }
   }
   else//没有分片直接保存
   {
    context.Request.Files[0].SaveAs(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName ));
   }
   context.Response.Write("ok");
  }

还存在一些问题没解决,虽然暂时满足需求:

1、如果上传并发超过1个的时候,就会出现一个分片上传服务器还没处理结束,第二个分片同时就到了,那样就会出现文件被占用的错误。
2、如果加锁的办法解决第一个问题,那加锁了就肯定会影响效率(同时只有一个进程能访问保存文件那段代码)。
3、文件的顺序问题,有个可能是第二个分片先到,然后第一个才到,那么就不能一次追加流到临时文件了,只能创建多个临时文件,待所有分片上传完成后,拼接成一个文件。

只是个Demo,希望有人帮助解决下存在的问题。

更多精彩内容,请点击《jQuery上传操作汇总》,进行深入学习和研究。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
[推荐]javascript 面向对象技术基础教程
Mar 03 Javascript
ExtJS 2.0实用简明教程 之ExtJS版的Hello
Apr 29 Javascript
如何制作浮动广告 JavaScript制作浮动广告代码
Dec 30 Javascript
深入理解JavaScript系列(43):设计模式之状态模式详解
Mar 04 Javascript
js命名空间写法示例
Dec 18 Javascript
原生JavaScript制作微博发布面板效果
Mar 11 Javascript
webpack学习--webpack经典7分钟入门教程
Jun 28 Javascript
vue如何使用 Slot 分发内容实例详解
Sep 05 Javascript
react高阶组件经典应用之权限控制详解
Sep 07 Javascript
百度地图去掉marker覆盖物或者去掉maker的label文字方法
Jan 26 Javascript
vue中利用Promise封装jsonp并调取数据
Jun 18 Javascript
JS实现简单的九宫格抽奖
Jun 28 Javascript
快速掌握jQuery插件WebUploader文件上传
Nov 07 #Javascript
jquery.validate表单验证插件使用方法解析
Nov 07 #Javascript
功能强大的jquery.validate表单验证插件
Nov 07 #Javascript
JS 实现Base64编码与解码实例详解
Nov 07 #Javascript
百度多文件异步上传控件webuploader基本用法解析
Nov 07 #Javascript
Angularjs的Controller间通信机制实例分析
Nov 07 #Javascript
jquery组件WebUploader文件上传用法详解
Oct 23 #Javascript
You might like
php多个字符串替换成同一个的解决方法
2013/06/18 PHP
php中Session的生成机制、回收机制和存储机制探究
2014/08/19 PHP
PHP中捕获超时事件的方法实例
2015/02/12 PHP
使用PHP生成图片的缩略图的方法
2015/08/18 PHP
yii2框架中使用下拉菜单的自动搜索yii-widget-select2实例分析
2016/01/09 PHP
搭建自己的PHP MVC框架详解
2017/08/16 PHP
PHP封装的非对称加密RSA算法示例
2018/05/28 PHP
获取任意Html元素与body之间的偏移距离 offsetTop、offsetLeft (For:IE5+ FF1 )[
2006/12/22 Javascript
比较简单实用的使用正则三种版本的js去空格处理方法
2007/11/18 Javascript
JQuery.uploadify 上传文件插件的使用详解 for ASP.NET
2010/01/22 Javascript
jquery 选择器引擎sizzle浅析
2013/02/06 Javascript
jQuery on方法传递参数示例
2014/12/09 Javascript
jQuery中:hidden选择器用法实例
2014/12/30 Javascript
jQuery实现平滑滚动到指定锚点的方法
2015/03/20 Javascript
EXT中单击button按钮grid添加一行(光标位置可设置)的实例代码
2016/06/02 Javascript
web.js.字符串与正则表达式操作
2017/05/13 Javascript
深入浅析angular和vue还有jquery的区别
2018/08/13 jQuery
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
2018/09/04 Javascript
layDate插件设置开始和结束时间
2018/11/15 Javascript
three.js搭建室内场景教程
2018/12/30 Javascript
Element Popover 弹出框的使用示例
2020/07/26 Javascript
JavaScript实现打字游戏
2021/02/19 Javascript
Python实现提取文章摘要的方法
2015/04/21 Python
python从入门到精通(DAY 2)
2015/12/20 Python
python3 拼接字符串的7种方法
2018/09/12 Python
Python3 Post登录并且保存cookie登录其他页面的方法
2018/12/28 Python
python 提取tuple类型值中json格式的key值方法
2018/12/31 Python
pandas之分组groupby()的使用整理与总结
2020/06/18 Python
图解Python中深浅copy(通俗易懂)
2020/09/03 Python
JVM是一个编译程序还是解释程序
2012/09/11 面试题
项目总经理岗位职责
2014/02/14 职场文书
森林防火标语
2014/06/23 职场文书
授权委托书格式范文
2014/08/02 职场文书
教师党员自我评价2015
2015/03/04 职场文书
Java方法重载和方法重写的区别到底在哪?
2021/06/11 Java/Android
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers