最近项目中需要使用到上传超大文件的功能,网上看了几个插件,个人比较喜欢的有fcup.js、Web Uploader。最后决定使用百度的webuploader插件,原因有以下三点:
1.所有的样式都可以自己写,比较灵活
2.支持大文件切片上传
3.支持多文件批量上传
如果不需要批量上传的项目可以使用fcup.js,因为使用起来真的很简单。
这是Web Uploader的demo与文档地址。
效果图:
其中wjh-2019-0001.rar与wjh-2019-0002.rar因大小超出10M自动分片上传
引入资源
<link rel="stylesheet" type="text/css" href="__STATIC__/webuploader/webuploader.css"/>
<link rel="stylesheet" type="text/css" href="__STATIC__/webuploader/webuploader-style.css"/>
<script type="text/javascript" charset="UTF-8" src="__STATIC__/webuploader/webuploader.js"></script>
<script type="text/javascript" charset="UTF-8" src="__STATIC__/webuploader/upload.js"></script>
以上几个资源已经上传,可以在百度网盘下载 提取码 f66j
webuploader.css与webuploader.js是Web Uploader官方下载的,引入即可
webuploader-style.css是上传页面的样式
upload.js是自己封装的js方法
需要自己根据项目调整的也就是webuploader-style.css与upload.js
HTML部分
<div id="uploader" class="wu-example">
<div class="btns">
<div id="picker">选择文件</div>
<div class="div-btn">
<div id="ctlBtn" class="btn-submit">开始上传</div>
</div>
<div class="div-btn">
<div id="cancle" class="btn-close" onClick="cdialog()">关闭</div>
</div>
</div>
<!--用来存放文件信息-->
<div class="clearfix" style="overflow-y:hidden;">
<div class="table_head clearfix">
<table class="webuploder-table">
<col width="150px">
<col width="60px">
<col width="150px">
<col width="60px">
<thead>
<tr>
<th class="text-center">文件名</th>
<th class="text-center">大小</th>
<th class="text-center">状态</th>
<th class="text-center">操作</th>
</tr>
</thead>
</table>
</div>
<div class="table_body clearfix">
<table id="file_table" class="webuploder-table">
<col width="150px">
<col width="60px">
<col width="150px">
<col width="60px">
<tbody id="thelist">
</tbody>
</table>
</div>
</div>
</div>
HTML调用js部分
$(function(){
var chunkSize = 10*1024*1024,//分片文件大小,超出此大小会自动分片
extensions = 'zip,rar,jpg,png,pdf',//可上传文件类型
path = 'upload/file';//文件上传服务器存储地址
var uploadSendData = {
// 选择文件的按钮。可选。
// 内部根据当前运行时创建,可能是input元素,也可能是flash.
pick: '#picker',
accept:{
title: 'Files',
extensions: extensions,
},
// swf文件路径
swf: '__STATIC__/webuploader/Uploader.swf',
// 文件接收服务端。
server: "{:url('Jhsoft_upload_save')}",
//是否允许在文件传输时提前把下一个文件准备好
prepareNextFile: true,
//是否要分片处理大文件
chunked: true,
//分片文件每片大小
chunkSize: chunkSize,
//如果某个分片由于网络问题出错,允许自动重传次数
chunkRetry: 2,
//上传并发数
threads: 3,
// 防止多次上传
duplicate : false,
//文件上传请求的参数表,每次发送都会发送此对象中的参数
formData: {
uid: 0,
md5: '',
path: path,
format : extensions,
maxSize: chunkSize,
},
}
webUploader_file(uploadSendData);
})
官方文档中所说的:WebUploader只包含文件上传的底层实现,不包括UI部分。所以交互方面可以自由发挥。这里的交互就是通过自己编写upload.js来实现的。
我这里只对几个事件进行了监控,fileQueued(当文件被添加)、uploadProgress(上传过程中,主要用于更新进度条)、uploadSuccess(上传成功)、uploadError(上传失败),这几个事件我想看了upload.js就应该明白是怎么使用的了。其他参数与事件可以自己去看官方文档,文档说的很详细。
后台PHP部分
public function Jhsoft_upload_save()
{
$is_success = false;
$message = '上传失败';
$uid = input('uid');//文件唯一性标识
$maxSize = input('maxSize/d', 31457280);
$path = input('path', 'upload/file');//文件最终保存路径
$fileName = input('name');
$fileSize = input('size');
$format = input('format', '*');//可上传文件类型
$chunks = input('chunks/d');//分片总数
$chunk = input('chunk/d');//当前分片索引
//分片上传
//$chunks是插件自动计算的大文件分片后总个数
if (isset($chunks) && $chunks > 1) {
if (!empty($uid)) {
$data = fileUploadChunks($fileName, $uid, $chunks, $chunk, $path);
$is_success = $data['flag'];
$message = $data['message'];
}
}
else {
$data = fileUploadOne($path);
$is_success = $data['flag'];
$message = $data['message'];
}
$restlt = array(
'is_success' => $is_success,
'message' => $message,
);
return json($restlt);
}
function fileUploadOne($path = 'upload/file', $upload_file_name = '')
{
$result = fileUpload($path, $upload_file_name);
return $result;
}
function fileUploadChunks($fileName, $uid, $fileSize, $chunks, $chunk, $path = 'upload/file')
{
$pathTmp = $path . "/" . $uid . date('Ymd');//临时分片文件路径
$fileInfoArray = pathinfo($fileName);
$ext = $fileInfoArray['extension'];//文件后缀
$upload_file_name = $uid . '_' . $chunk;//临时分片文件名
$result = fileUpload($pathTmp, $upload_file_name);
if ($result['flag'] == 1) {
// 单文件上传成功
// 判断所有分片是否都上传完毕了
$complete = true;
for ($i = 0; $i < $chunks; $i++) {
if (!file_exists($pathTmp . "/" . $uid . "_" . $i)) {
$complete = false;
break;
}
}
//如果所有分片都有的话就开始合并
if ($complete) {
$newName = time() . mt_rand(100, 999);//最终文件名
$fileSrc = $path . '/' . $newName . '.' . $ext;
$fp = fopen($fileSrc, "ab");
for ($i = 0; $i < $chunks; $i++) {
$tmp_file = $pathTmp . "/" . $uid . "_" . $i;
$handle = fopen($tmp_file, "rb");
fwrite($fp, fread($handle, filesize($tmp_file)));
fclose($handle);
unset($handle);
unlink($tmp_file);//合并完毕的文件就删除
}
fclose($fp);
rmdir($pathTmp);//删除文件夹
$result = array(
'message' => '上传成功',
'flag' => 1,
);
}
}
return $result;
}
以上php中用到的fileUpload是封装好的一个单文件上传方法(不会的话可以去去度娘下,很简单的),返回的内容主要是flag(是否成功),message(说明)。
这几个php方法主要是为了说明分片上传时,先将WebUploader插件拆分好的每个单文件上传到临时文件夹,在每个单文件上传完成后判断临时文件夹中是否所有文件都已经存在了,如果存在就遍历所有文件内容,将内容写入到一个新创建的文件中,再删除原来的文件临时文件夹完成大文件上传