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 相关文章推荐
利用js的Node遍历找到repeater的一个字段实例介绍
Apr 25 Javascript
jquery下div 的resize事件示例代码
Mar 09 Javascript
JQuery复制DOM节点的方法
Jun 11 Javascript
JavaScript 字符串常用操作小结(非常实用)
Nov 30 Javascript
js实现显示手机号码效果
Mar 09 Javascript
JS实现图片预览的两种方式
Jun 27 Javascript
vue项目中vue-i18n和element-ui国际化开发实现过程
Apr 25 Javascript
vue如何通过id从列表页跳转到对应的详情页
May 01 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
Apr 14 Javascript
express启用https使用小记
May 21 Javascript
初试vue-cli使用HBuilderx打包app的坑
Jul 17 Javascript
原生js实现点击按钮复制内容到剪切板
Nov 19 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
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
ECMall支持SSL连接邮件服务器的配置方法详解
2014/05/19 PHP
php关联数组与索引数组及其显示方法
2018/03/12 PHP
一个对于Array的简单扩展
2006/10/03 Javascript
Javascript 解疑
2009/11/11 Javascript
五段实用的js高级技巧
2011/12/20 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
判断客户浏览器是否支持cookie的示例代码
2013/12/23 Javascript
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
2014/06/26 Javascript
AngularJS入门教程(一):静态模板
2014/12/06 Javascript
jQuery中:disabled选择器用法实例
2015/01/04 Javascript
jQuery+css3动画属性制作猎豹浏览器宽屏banner焦点图
2015/03/16 Javascript
基于JavaScript实现简单的随机抽奖小程序
2016/01/05 Javascript
vuejs指令详解
2017/02/07 Javascript
Bootstrap 模态框多次显示后台提交多次BUG的解决方法
2017/12/26 Javascript
react的滑动图片验证码组件的示例代码
2019/02/27 Javascript
详解vue中使用axios对同一个接口连续请求导致返回数据混乱的问题
2019/11/06 Javascript
用python删除java文件头上版权信息的方法
2014/07/31 Python
python实现自动登录人人网并采集信息的方法
2015/06/28 Python
pytorch训练imagenet分类的方法
2018/07/27 Python
pygame游戏之旅 添加游戏介绍
2018/11/20 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
python 在屏幕上逐字显示一行字的实例
2018/12/24 Python
selenium+python自动化测试之多窗口切换
2019/01/23 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
2020/10/27 Python
AP澳洲中文网:澳洲正品直邮,包税收件无忧
2019/07/12 全球购物
北欧最好的童装网上商店:Babyshop
2019/09/15 全球购物
写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度
2015/11/18 面试题
房产销售经理职责
2013/12/20 职场文书
幼儿园校车司机的岗位职责
2014/01/30 职场文书
指导教师评语
2014/04/26 职场文书
家庭贫困证明范本(经典版)
2014/09/22 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
SpringBoot实现quartz定时任务可视化管理功能
2021/08/30 Java/Android
Python中request的基本使用解决乱码问题
2022/04/12 Python