原理:简单来说,就是将前端需要上传的大文件拆分成为无数个小文件进行循环上传,后端接受的时候进行判断,往同一个文件里面添加,代码如下:
- 前段
<input type="file" onchange="addAnnex('uploadAnnex-2')" id="uploadAnnex-2"/>
<script>
//上传附件,监听input框onchange时间
function addAnnex(id) {
var file = document.getElementById(id).files[0];
//调用分片上传方法
PostFile(file,0,id);
}
//执行分片上传
function PostFile(file,i,domId,json){
//获取上传参数
var name = file.name,//文件名
size = file.size,//文件大小
shardSize = 1024 * 1024,//设置每个分片大小,我这是1M一个
shardCount = Math.ceil(size / shardSize);//计算总片数
//容错
if(i >= shardCount){
return;
}
//计算文件截取起始位置
var start = i * shardSize;
var end = start + shardSize;
//将文件进行切片
var packet = file.slice(start, end);
//组织post表单数据
var form = new FormData();
form.append("name", name);
form.append("upload", packet); //slice方法用于切出文件的一部分
form.append("total", shardCount); //总片数
form.append("index", i + 1); //当前是第几片
//我这用这个变量标记当前传入的是否为第一片,存在值不是第一片,需要将之前的保存的文件名及需要的信息添加之表单数据中
if(json){
form.append('shard_name',json.name);
form.append('id',json.id);
}
//开始上传
$.ajax({
url: baseUrl,//你的url
type: "POST",
data: form,
async:false,
timeout: 10000,
processData: false,
contentType: false,
success: function (json) {
//等于200,全部上传完成
if(json.code == 200){
//此处实现你上传完成的逻辑
}else if(json.code == 201){
//继续上传下一片,并将返回的结果加入到数据中
form = '';
i++;
PostFile(file, i,domId,json.result);
}else{
//出现错误
jqtoast(json.msg);
}
},
error: function (){
}
});
}
</script>
- 后端
我使用了easyswoole框架,其实原理都一样
//获取上传的文件数据
$request= $this->request();
$file = $request->getUploadedFile('upload');
//获取post删除
$post = $this ->POST;
//判断是否存在错误
if($file ->getError()){
return $this ->writeJson(401,'文件上传失败');
}
//限制文件大小,大于100M的不允许上传
$size = $file -> getSize();
if($size / (1024*1024) > 100){
return $this ->writeJson(401,'文件太大了');
}
//判断是否传入分片文件名,不存在则表示上传第一片
if(empty($post['shard_name'])){
//获取文件后缀
$ext = explode('.',$post['name']);
$ext = array_pop($ext);
//定义新的文件名
$name = md5('product'.time());
$name = substr($name,5,10).'.'.$ext;
//定义文件保存路径
$path = EASYSWOOLE_ROOT.'/Static/UploadFile/'.$name;
//保存文件
if(!($file -> moveTo($path))){
return $this ->writeJson(400,'文件保存失败');
}
//组织保存数据
$data = [
'user_id' => $uid,
'product_id' => 0,
'name' => $name,
'src_name' => $post['name'],
'cdt' => date('Y-m-d H:i:s')
];
//验证数据是否保存成功
try{
$model = new File();
$insertId = $model ->insert($data);
if(empty($insertId)){
return $this ->writeJson(400,'文件上传失败');
}
$data['id'] = $insertId;
}catch (\Exception $exception){
Logger::getInstance()->error($exception ->getMessage(),'文件上传失败');
return $this ->writeJson(400,'文件上传失败');
}
//组织返回数据
$result = [
'id' => $insertId,
'name' => $name,
'src_name' => $post['name'],
];
}else{
//定义文件保存路径
$path = EASYSWOOLE_ROOT.'/Static/UploadFile/'.$post['shard_name'];
file_put_contents($path,$file->getStream(),FILE_APPEND);
//组织返回数据
$result = [
'id' => $post['id'],
'name' => $post['shard_name'],
'src_name' => $post['name'],
];
}
//判断是否上传完毕
if($post['total'] == $post['index']){
//上传完毕
return $this ->writeJson(200,'ok',$result);
}else{
return $this ->writeJson(201,'ok',$result);
}