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 相关文章推荐
Array对象方法参考
Oct 03 Javascript
Javascript中获取出错代码所在文件及行数的代码
Sep 23 Javascript
jQuery EasyUI API 中文文档 - EasyLoader 加载器
Sep 29 Javascript
JavaScript时间转换处理函数
Apr 14 Javascript
jQuery实现的表头固定效果实例【附完整demo源码下载】
Aug 01 Javascript
jquery操作ID带有变量的节点实例
Dec 07 Javascript
fullPage.js和CSS3实现全屏滚动效果
May 05 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
Jul 11 Javascript
BootStrap模态框不垂直居中的解决方法
Oct 19 Javascript
微信公众平台获取access_token的方法步骤
Mar 29 Javascript
Vue基于iview实现登录密码的显示与隐藏功能
Mar 06 Javascript
vue 函数调用加括号与不加括号的区别
Oct 29 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
定制404错误页面,并发信给管理员的程序
2006/10/09 PHP
php中的mongodb select常用操作代码示例
2014/09/06 PHP
thinkphp中memcache的用法实例
2014/11/29 PHP
php实现多维数组中每个单元值(数字)翻倍的方法
2015/02/16 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
js函数般调用正则
2008/04/08 Javascript
javascript 函数调用规则
2009/08/26 Javascript
一个XML格式数据转换为图表的例子
2010/02/09 Javascript
JS求平均值的小例子
2013/11/29 Javascript
jQuery获取选中内容及设置元素属性的方法
2014/07/09 Javascript
Javascript闭包用法实例分析
2015/01/23 Javascript
javascript获取wx.config内部字段解决微信分享
2016/03/09 Javascript
Vue.js 表单校验插件
2016/08/14 Javascript
Node.js的基本知识简单汇总
2016/09/19 Javascript
jQuery+HTML5实现弹出创意搜索框层
2016/12/29 Javascript
原生js实现验证码功能
2017/03/16 Javascript
jQuery实现的简单对话框拖动功能示例
2018/06/05 jQuery
微信小程序城市选择及搜索功能的方法
2019/03/22 Javascript
ES6 proxy和reflect的使用方法与应用实例分析
2020/02/15 Javascript
vue实现图片按比例缩放问题操作
2020/08/11 Javascript
解决Vue-cli无法编译es6的问题
2020/10/30 Javascript
简单学习Python time模块
2016/04/29 Python
Python解决N阶台阶走法问题的方法分析
2017/12/28 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
Python3.5面向对象与继承图文实例详解
2019/04/24 Python
Python Tkinter 简单登录界面的实现
2019/06/14 Python
Django处理Ajax发送的Get请求代码详解
2019/07/29 Python
Pandas把dataframe或series转换成list的方法
2020/06/14 Python
新西兰杂志订阅:isubscribe
2019/08/26 全球购物
运动会广播稿200字
2014/01/15 职场文书
开服装店计划书
2014/08/15 职场文书
暑假学习心得体会
2014/09/02 职场文书
银行业务授权委托书
2014/10/10 职场文书
党小组鉴定意见
2015/06/02 职场文书
小学音乐课歌曲《堆雪人》教学反思
2016/02/18 职场文书
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
2021/06/05 Python