使用Webuploader大文件分片传输
背景:50G大文件的HTTP上传至服务器。
好了,根据这个命题,可以开始研究我们怎么做才能把这么大的文件上传成功。
分片上传是肯定的,断点续传也是要有的,进度可视化那就更好了,基于这些,我选择了Webuploader在前端进行分片上传。
为什么选择它呢,好吧,它简单,易上手,好排错,文档多......
实际是我懒......
网上的教程大部分是复制粘贴,借鉴起来也很无奈,推荐一个我觉得比较实在的
https://www.cnblogs.com/baiyunchen/p/5383507.html
本篇Demo地址,欢迎各位大佬指点
https://github.com/papapalh/Big_File
一:开始
新建立项目,这里用了php7.0版本后台处理。
没啥说的,下载WebUploader的包http://fex.baidu.com/webuploader/download.html
jQuery也是必须的,因为就是依赖jQ的。
好了,可以初始化我们的上传组件了,介绍一下这里Demo的配置
- // 创建上传
- var uploader = WebUploader.create({
- swf: '/webuploader-0.1.5/Uploader.swf',
- server: 'index.php', // 服务端地址
- pick: '#picker', // 指定选择文件的按钮容器
- resize: false,
- chunked: true, //开启分片上传
- chunkSize: 1024*1024*4, //每一片的大小
- chunkRetry: 100, // 如果遇到网络错误,重新上传次数
- threads: 3, //上传并发数。允许同时最大上传进程数。
- });
- // 上传提交
- $("#ctlBtn").click(function () {
- console.log('准备上传...');
- uploader.upload();
- });
二:上传分片
好了,这样看吧,一个文件会被切分成为若干个小片段发送到服务器中。
但是,我们之后要做的断点续传,如何以唯一的标识来记录这个文件呢。
用MD5吧,简单粗暴,我觉得肯定有更好的办法,但是由于是DEMO,先整体跑下来在说。
下面这段代码做了这些事
- 添加文件进来时计算文件的MD5,用于文件的唯一标识
- 检查之前有没有上传一半出问题的,如果出问题了,那么,以MD5命名的文件夹肯定会有,那么我们传之后的就好了。
- 我给这个状态绑定了一个参数Status
- // 当有文件被添加进队列的时候-md5序列化
uploader.on('fileQueued', function (file) {
console.log("正在计算MD5值...");- uploader.md5File(file)
- .then(function (fileMd5) {
- file.wholeMd5 = fileMd5;
- file_md5 = fileMd5;
- console.log("MD5计算完成。");
- console.log("正在查找有无断点...");
- $.post('check.php', {md5: file_md5}, function (data) {
- data = JSON.parse(data);
- switch (data.code) {
- // 断点
- case '0':
- console.log('有断点.正在准备从断点处上传文件。');
- for (var i in data.block_info) {
- block_info.push(data.block_info[i]);
- }
- file.status = 0;
- break;
- // 无断点
- case '1':
- console.log('无断点.上传新文件。');
- file.status = 1;
- break;
- }
- })
- });
- });
check.php
检查有没有遗留的文件夹,有的话说明你之前上传过,这些我就不要了,并返回上传成功的分片 JSON
- <?php
- // 接收相关数据
- $post = $_POST;
- // 找出分片文件
- $dir = '/var/www/'.$post['md5'];
- // 有断点
- if (file_exists($dir)) {
- // 找出上传成功的所有文件
- $block_info=scandir($dir);
- // 除去无用文件
- foreach ($block_info as $key => $block) {
- if ($block == '.' || $block == '..') unset($block_info[$key]);
- }
- echo json_encode(["code"=>"0" , 'block_info' => $block_info]);
- }
- // 无断点
- else {
- echo json_encode(["code"=>"1"]);
- }
index.php
接受传入文件,写入临时文件,这里其实也应该用个MD5来检查分片
- <?php
- // 接收相关数据
- $post = $_POST;
- $file = $_FILES;
- $status = $post['status'];
- // 建立临时目录存放文件-以MD5为唯一标识
- $dir = "/var/www/" . $post['md5value'];
- // 断点上传
- if ($status == '0') {
- // 获取分片文件内容
- $block_info=scandir($dir);
- // 除去无用文件
- foreach ($block_info as $key => $block) {
- if ($block == '.' || $block == '..') unset($block_info[$key]);
- }
- }
- // 直接上传
- elseif($status == '1') {
- if (!file_exists($dir)) {
- mkdir ($dir,0777,true);
- }
- // 移入缓存文件保存
- move_uploaded_file($file["file"]["tmp_name"], $dir.'/'.$post["chunk"]);
- }
三:断点.跳过已有分片
这个地方是困扰了我很长时间的地方
官方API对于跳过分片的内容也找不到,所以单独把他拿出来,日后也方便查看
刚刚我们把如果有断点的,我们把上传成功的分片数组拿出来,比对一下,如果有,就不上传了
- // 发送前检查分块,并附加MD5数据
- uploader.on('uploadBeforeSend', function( block, data ) {
- var file = block.file;
- var deferred = WebUploader.Deferred();
- data.md5value = file.wholeMd5;
- data.status = file.status;
- if ($.inArray(block.chunk.toString(), block_info) >= 0) {
- console.log("已有分片.正在跳过分片"+block.chunk.toString());
- deferred.reject();
- deferred.resolve();
- return deferred.promise();
- }
- });
这样就完成了我们对于断点和分片的处理
四:合并
首先你得告诉我,你上传完了,该合并了
- // 上传完成后触发
- uploader.on('uploadSuccess', function (file,response) {
- console.log("上传分片完成。");
- console.log("正在整理分片...");
- $.post('merge.php', { md5: file.wholeMd5, fileName: file.name }, function (data) {
- var object = JSON.parse(data);
- if (object.code) {
- console.log("上传成功");
- }
- });
- });
这是Webuploader它上传成功的一个回调
告诉了merge.php
让开吧,我要合并了,就这个意思吧
- <?php
- // 接收相关数据
- $post = $_POST;
- // 找出分片文件
- $dir = '/var/www/'.$post['md5'];
- // 获取分片文件内容
- $block_info = scandir($dir);
- // 除去无用文件
- foreach ($block_info as $key => $block) {
- if ($block == '.' || $block == '..') unset($block_info[$key]);
- }
- // 数组按照正常规则排序
- natsort($block_info);
- // 定义保存文件
- $save_file = "/var/www/".$post['fileName'];
- // 没有?建立
- if (!file_exists($save_file)) fopen($post['fileName'], "w");
- // 开始写入
- $out = @fopen($save_file, "wb");
- // 增加文件锁
- if (flock($out, LOCK_EX)) {
- foreach ($block_info as $b) {
- // 读取文件
- if (!$in = @fopen($dir.'/'.$b, "rb")) {
- break;
- }
- // 写入文件
- while ($buff = fread($in, 4096)) {
- fwrite($out, $buff);
- }
- @fclose($in);
- @unlink($dir.'/'.$b);
- }
- flock($out, LOCK_UN);
- }
- @fclose($out);
- @rmdir($dir);
- echo json_encode(["code"=>"0"]);//随便返回个值,实际中根据需要返回
看着挺长,实际就一个意思,按顺序写入。
五:其他
特殊效果也加了一点,可以试试
- // 文件上传过程中创建进度条实时显示。
- uploader.on('uploadProgress', function (file, percentage) {
- $("#percentage_a").css("width",parseInt(percentage * 100)+"%");
- $("#percentage").html(parseInt(percentage * 100) +"%");
- });
- // 上传出错处理
- uploader.on('uploadError', function (file) {
- uploader.retry();
- });
- // 暂停处理
- $("#stop").click(function(e){
- log("暂停上传...");
- uploader.stop(true);
- })
- // 从暂停文件继续
- $("#start").click(function(e){
- log("恢复上传...");
- uploader.upload();
- })
五:PS
- 其实需要做的还有很多,各种验证,一定要保证分片的正确上传和写入。
- 还有各种的错误处理,之后如果运用到项目中的话,也一定会回来补充需要注意的地方
- 作为这个知识领域的小白,感觉很奇妙,也很有意思。
六:展示效果
可以对页面进行下改动,也挺漂亮了,感谢。
使用Webuploader大文件分片传输的更多相关文章
- Webuploader 大文件分片上传
百度Webuploader 大文件分片上传(.net接收) 前阵子要做个大文件上传的功能,找来找去发现Webuploader还不错,关于她的介绍我就不再赘述. 动手前,在园子里找到了一篇不错的分片 ...
- 百度Webuploader 大文件分片上传(.net接收)
前阵子要做个大文件上传的功能,找来找去发现Webuploader还不错,关于她的介绍我就不再赘述. 动手前,在园子里找到了一篇不错的分片上传的帖子,参考之后,踏出了第一步.此文记录我这次实践的点滴,仅 ...
- 百度Webuploader 大文件分片上传(.net接收)
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- asp.net mvc+webuploader大文件分片上传
首先是前端: var GUID = WebUploader.Base.guid();//一个GUID uploadereditsVideo = WebUploader.create({ // swf文 ...
- webuploader大文件分片,多线程总结
项目的新需求是用webuploader来做一个多文件,多线程,并且可以进行分块上传的要求,这些在前面的一篇文章当中足够使用了,但是现在又来一个新的需求,要求上传失败的文件进行重新的上传……心里默默说句 ...
- ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示
本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...
- .NetCore+WebUploader实现大文件分片上传
项目要求通过网站上传大文件,比如视频文件,通过摸索实现了文件分片来上传,然后后台进行合并. 使用了开源的前台上传插件WebUploader(http://fex.baidu.com/webupload ...
- thinkphp+webuploader实现大文件分片上传
大文件分片上传,简单来说就是把大文件切分为小文件,然后再一个一个的上传,到最后由这些小文件再合并成原来的文件 webuploader下载地址及其文档:http://fex.baidu.com/webu ...
- 在React中使用WebUploader实现大文件分片上传的踩坑日记!
前段时间公司项目有个大文件分片上传的需求,项目是用React写的,大文件分片上传这个功能使用了WebUploader这个组件. 具体交互是: 1. 点击上传文件button后出现弹窗,弹窗内有选择文件 ...
随机推荐
- Harbor api 操作
harbor 的版本为 1.5.2 为 Harbor 配置 swagger 官网参考: https://github.com/goharbor/harbor/blob/v1.5.2/docs/conf ...
- 1474 十进制转m进制
1474 十进制转m进制 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 将十进制数n转换成m进制数 m ...
- PHP与.Net的区别(一)接口
一.关于接口成员 PHP的接口成员只能包括两种: 1.函数签名 2.常量 .Net的接口成员只能包括三种: 1.函数签名 2.属性(注意:是属性,不是字段) 3.事件 4.索引器(也叫有参属性)
- docker第一章:docker核心概念及centos6下安装
Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...
- Google Chrome 下载&绿化&增强
Chrome下载 Google Chrome 已经可以在线更新,虽然比较慢! 国内常用的更新地址有两处:chromedownloads 和 shuax(耍下): https://www.chromed ...
- 阿里SopHix热修复框架
2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker(Bugly sdk也集成Tikner ...
- JQuery实战中遇到的两个小问题$(document).ready() 、bind函数的参数传递问题
一.$(document).ready() 与 window.onload的区别 1.执行时间 window.onload 必须等到页面内所有元素(包括图片 css js等)加载完毕后才会执行. $( ...
- 用python连接mysql失败总结
所用环境:python3,pycharm2018.2.4 先用mysql创建用户并授予相关权限 在我用python连接mysql时,一直提示连接不上,报错原因就是,用户没有被给予相关权限,比如查询,插 ...
- CSS| 框模型-padding
例子:
- Python交互模式下代码自动补全
这个功能是以lib的形式提供的,配置写到home下的.pythonrc文件中, 并设置好环境变量让python启动时执行初始化: # ~/.pythonrc # enable syntax compl ...