断点续传、支持超大文件(无需安装客户端插件)
来源:互联网 发布:网络被限制了怎么办 编辑:程序博客网 时间:2024/06/06 12:49
首先声明,这不是一个理论性的文章,是经过的实践证明的,文章的结尾会附带demo,demo是比较简单的,没有经过封装,一看就懂
准备工作:
plupload,版本应该是随意的,我使用的哪个版本也忘记了。
简单的介绍plupload,plupload就是一个在客户端进行了文件切割之后上传的javascript库,它有5种不同的上传技术,看浏览器的支持情况,或许会用html5、fllash之类的技术,但是这些都是内部实现的,我们无需关心,后台是用php实现,也能找到asp.net相关的例子。
早期使用它进行友好的进度显示等...当然现在经过这几年的jquery革命,产生的类似插件也多如牛毛,本来只是重点讲解思路。理论上用其它插件依然能办到。
思路:在文件切割分块之后、上传之前,通过ajax去检测服务器上已经存在的文件区块,然后设置plupload的起始区块,以达到我们断点续传的目地,呵呵,是不是很简单?看代码
首先我上一个asp.net mvc的后台代码,用于保存上传文件与读取已存在区块的功能。
/// <summary> /// 文件上传 /// </summary> /// <returns></returns> public JsonResult plupload(string name) { string[] dd = Request.Headers.AllKeys; string msg = string.Empty; int chunk = Convert.ToInt32(Request["chunk"]); //当前分块 int chunks = Convert.ToInt32(Request["chunks"]);//总的分块数量 long hcouns = 0; foreach (string upload in Request.Files) { if (upload != null && upload.Trim() != "") { string path = AppDomain.CurrentDomain.BaseDirectory + "Temp\\"; if (!Directory.Exists(path)) //判断给定的路径上是否存在该目录 { Directory.CreateDirectory(path); //不存在则创建该目录 } System.Web.HttpPostedFileBase postedFile = Request.Files[upload]; //获取客户端上载文件的集合 string filename1 = Path.GetFileName(postedFile.FileName); //获取客户端上传文件的名称及后缀 string filename = name; // string newFileName = filename; if (chunks > 1) { newFileName = chunk + "_" + filename; //按文件块重命名块文件 } string fileNamePath = path + newFileName; //将块文件和临时文件夹路径绑定 if (chunks > 0) { for (int i = 0; i < chunks; i++) { //检测已存在磁盘的文件区块 if (!System.IO.File.Exists(path+i.ToString() + "_" + filename) && i != chunk) { hcouns = i * postedFile.ContentLength; break; } } } postedFile.SaveAs(fileNamePath); //保存上载文件内容 if (chunks > 1 && chunk + 1 == chunks) //判断块总数大于1 并且当前分块+1==块总数(指示是否为最后一个分块) { using (FileStream fsw = new FileStream(path + filename, FileMode.Create, FileAccess.Write)) { BinaryWriter bw = new BinaryWriter(fsw); // 遍历文件合并 for (int i = 0; i < chunks; i++) { bw.Write(System.IO.File.ReadAllBytes(path + i.ToString() + "_" + filename)); //打开一个文件读取流信息,将其写入新文件 System.IO.File.Delete(path + i.ToString() + "_" + filename); //删除指定文件信息 bw.Flush(); //清理缓冲区 } } } } } return Json(new { jsonrpc = "2.0", result = "", id = "id", hcount = "" + hcouns.ToString() + "" }); } /// <summary> /// 检测文件已有区块 /// </summary> /// <returns></returns> [HttpPost] public JsonResult checkplupload() { string fileName = Request["fileName"].ToString(); //文件名称 long Size = Request["size"] == null ? 0 : Convert.ToInt64(Request["size"]); //文件的分块大小 int fileCount = Request["maxFileCount"] == null ? 0 : Convert.ToInt32(Request["maxFileCount"]); //文件一共的分块数量。比如1G以20M分块,则有50块。 //上面变量通过加载文件的时候通过ajax方式提交过来 long hcouns = 0; string path = AppDomain.CurrentDomain.BaseDirectory + "Temp\\"; if (fileCount > 0) { for (int i = 0; i < fileCount; i++) { //检测已存在磁盘的文件区块 if (!System.IO.File.Exists(path + i.ToString() + "_" + fileName)) { //你懂的,如果服务器上不存在如 i_文件名这个文件,那证明客户端应该从这个字节开始往服务器上传。 hcouns = i * Size; //服务器已存在区块的总字节数 break; } } } //返回到客户端 return Json(new { result = hcouns }); }
上面这个代码应该 是通俗易懂的,第一个方法用于接收文件上次,第二个则是上传之前的检测。
接着我们应该在什么地方来使用它,用过pupload的都知道它里面存在着很多回调函数,包括上传前、分块完成之后.....很多!
那么到底应该在哪个回调函数的时候进行检测才能达到我们的目地?通过API查找,我们找到了一个
监听函数参数:(uploader,files)
uploader
为当前的plupload实例对象,files
为一个数组,里面的元素为本次添加到上传队列里的文件对象
接着上我修改之后的代码:
uploader.bind('FilesAdded', function(up, files) { var DATA={ fileName:files[0].name, size:up.settings.chunk_size, maxFileCount:Math.ceil(files[0].size/up.settings.chunk_size) }; $AjaxPost("/Home/checkplupload",DATA,function(dy){ files[0].loaded=dy.result; });self._trigger('selected', null, { up: up, files: files } );// re-enable sortableif (self.options.sortable && $.ui.sortable) {self._enableSortingList();}self._trigger('updatelist', null, { filelist: self.filelist });if (self.options.autostart) {// set a little delay to make sure that QueueChanged triggered by the core has time to completesetTimeout(function() {self.start();}, 10);}});
代码中的DATA为我自己构造的一个参数,$AjaxPost是我自己写的一个ajax请求方法,目标地址就是我们刚刚第一个c#代码中的检测文件区块部分。(实际这里应该是一个for循环去请求,因为它是支持多文件同时上传的,这里用的是单文件,自己改改即可)。最后在ajax请求完成的回调中,我设置了files[0].loaded,也就是设置了文件的开始区块。
直接的效果就是:假设我上传一个5GB的文件,2M/块进行上传,可能会在磁盘上形成2500多个2M大小的区块,如果当用户上传到2000块的时候,断网了....传统的方式就悲剧了,联网后又得重新上传,而经过这样的改造之后,在用户再此上传时首先会检测文件咋服务器上是否已经存在区块了,如果已经存在了2000块,那么就会把文件的区块索引改成2000,直接从2001块开始上传。
此解决方案本来已在项目中应用,当然:真正应用到项目时可能会和数据库、文件MD5等许多关联,关于其它问题,不在本文讨论范围内。
UpLoadFile MVC完整Demo支持断点续传
- 断点续传、支持超大文件(无需安装客户端插件)
- 超大文件下载类 支持2g以上文件 支持断点续传
- G级超大文件 断点续传 上传控件 silverupload 支持md5验证 支持跨域上传
- PHP 大文件下载,文件传输,支持断点续传。 2g以上超大文件也有效
- PHP超大文件下载,断点续传下载
- PHP超大文件下载,断点续传下载
- PHP超大文件下载,断点续传下载
- installgithub-支持断点续传下载GitHubDesktop离线安装文件
- 解决PHP超大文件下载,断点续传下载的方法详解
- 解决PHP超大文件下载,断点续传下载的方法详解
- java 文件上传支持断点续传
- golang ftp客户端示例 支持断点续传
- 支持超大文件的tail命令
- 用apache FTP client实现FTP客户端--支持断点续传和中文文件 .
- plsql安装--无需安装oracle客户端
- plsql安装--无需安装oracle客户端
- XCLNetFileReplace(文件名文件内容批量替换工具),支持Word/Excel/文本文件(无需安装office)
- 利用Winsock下载文件(支持断点续传)
- nginx: [warn] conflicting server name "这里是域名 eg:abc.com" on 0.0.0.0:80, ignored解决方法
- 第15周项目 3.3 OJ
- 使用autobench进行web压力测试
- 几种Socket服务器模型比较!
- 设计模式六大原则(6):开闭原则
- 断点续传、支持超大文件(无需安装客户端插件)
- CSDN上开启我的技术成长之路
- 监听Android屏幕是否锁屏
- Oracle存储过程记录异常
- PBEWithMD5AndDES加密 解密
- dataload简单用法
- 加载UFT场景恢复
- mysql多表连接
- 第13条:以对象来管理资源