现在的项目开发基本上都用到了上传文件功能,或图片,或文档,或视频。我们常用的常规上传已经能够满足当前要求了,
然而有时会出现如下问题:
- 文件过大(比如1G以上),超出服务端的请求大小限制;
- 请求时间过长,请求超时;
- 传输中断,必须重新上传导致前功尽弃;
- 设置了webconfig和iis后还是不能上传成功;
- 不想使用FTP,只想用http。
我们这里只讲分片上传,至于断网续传和秒传已经写好demo,下载路径放在文末,有兴趣的可以下载下来自己玩玩。
分片上传demo下载地址:https://pan.baidu.com/s/1osGyv2qYzTmtNIImqkcKvw 提取码:ie57
分片上传、断网续传、秒传demo下载地址:https://pan.baidu.com/s/1TuvGR6qUcKLMFjZGaQl5vg 提取码:aej4
http的网络请求中本身就已经具备了分片上传功能,那么什么是分片上传?我们来看看:
分片上传原理
片上传支持将一个文件切割为一系列特定大小的数据片,分别将这些小数据片上传到服务端,全部上传完后再在服务端将这些数据片合并成为一个资源。
分片上传引入了两个概念:块(Block)和片(Chunk)。每个块由一到多个片组成,而一个资源则由一到多个块组成。他们之间的关系可以用下图表述:
块和片是上传过程中作为临时存储的单位。服务端会以约七天为单位的周期清除上传后未被合并为块(文件)的数据片(块)。
与分片上传相关的 API 有:创建块(mkblk)、上传片(bput)、创建文件(mkfile)。一个完整的分片上传流程可用下图表示:
其中的关键点如下:
将待上传的文件按预定义块大小切分为若干个块(每块大小不大于 4MB:块的大小可以自定义)。如果这个文件小于 4MB,就只有一个块。
将每个块再按预定义的片大小切分为若干个片,先在服务端创建一个相应块(通过调用mkblk,并带上第一个片的内容),然后再循环将所有剩下的片全部上传(通过调用bput,从而完成一个块的上传)
在所有块上传完成后,通过调用mkfile将这些上传完成的块信息再严格的按顺序组装出一个逻辑资源的元信息,从而完成整个资源的分片上传过程。
在这个理论基础上,结合WebUploade插件(百度上传插件)和net mvc进行demo编写,老规矩,demo在文末,可以下载。
我们看一下效果图:
分片上传:
上传中(图一)
上传成功(图二)
分片、断网(暂停)、秒传:
上传中(图一)
上传成功(图二)
代码展示:
下载webuploader插件后引入项目中,
主要引用文件:
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<link href="~/Content/webuploader.css" rel="stylesheet" />
<script src="~/Scripts/webuploader.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
前端完整代码:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <script src="~/Scripts/jquery-1.10.2.min.js"></script> <link href="~/Content/webuploader.css" rel="stylesheet" /> <script src="~/Scripts/webuploader.js"></script> <script src="~/Scripts/bootstrap.min.js"></script> <div id="uploader" class="wu-example"> <!--用来存放文件信息--> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="picker">选择文件</div> <input id="ctlBtn" type="button" value="开始上传" class="btn btn-default" /> </div> </div> <table width="50%" border="1" class="fileList_parent"> <thead> <tr style="background-color:#DADADA"> <th>文件名称</th> <th>类型</th> <th>大小</th> <th>进度</th> <th>说明</th> </tr> </thead> <tbody class="fileList"> </tbody> </table> </body> </html> <script> var applicationPath = window.applicationPath === "" ? "" : window.applicationPath || "../../";