注: 本文大致上是借鑑於社群的這篇文章, 大檔案傳輸解決方案:分片上傳 / 下載限速
html
:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#progress{
display: inline-block;
width: 300px;
height: 20px;
background-color:#f7f7f7;
box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);
border-radius:4px;
background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);
}
#finish{
background-color: #149bdf;
background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);
background-size:40px 40px;
display: inline-block;
height: 20px;
}
</style>
</head>
<body>
<input type="file" style="width: 200px;" id="upload" />
<span id="progress" style="text-align: left;">
<span id="finish" style="width: 0%;" progress="0"></span>
</span>
</body>
</html>
javascript
:
let upload = document.getElementById("upload");
var uploadObj = new Upload();
upload.onchange = function(){
uploadObj.addFileAndSend(this,'finish','ppt');
}
function Upload(){
var xhr = new XMLHttpRequest();
var form_data = new FormData();
const LENGTH = 1024 * 1024 *2;
var start = 0;
var end = start + LENGTH;
var blob;
var blob_num = 1;
var is_stop = 0;
//對外方法,傳入檔案物件
// that 是input物件, idName 是進度條id名稱, type 是上傳檔案分類, 可以用此來區分上傳檔案目錄
this.addFileAndSend = function(that,idName,type){
var file = that.files[0];
blob = cutFile(file);
sendFile(blob,file,idName,that,type);
blob_num += 1;
}
//切割檔案
function cutFile(file){
var file_blob = file.slice(start,end);
start = end;
end = start + LENGTH;
return file_blob;
};
//傳送檔案
function sendFile(blob,file,idName,uploadObj,type){
var form_data = new FormData();
var total_blob_num = Math.ceil(file.size / LENGTH);
form_data.append('file',blob);
form_data.append('blob_num',blob_num);
form_data.append('total_blob_num',total_blob_num);
form_data.append('file_name',file.name);
form_data.append('file_type',type);
xhr.open('POST','後端上傳路由',false);
xhr.onreadystatechange = function () {
if (xhr.readyState==4 && xhr.status==200){
let responseMessage = JSON.parse(xhr.responseText);
if(responseMessage['code'] == 1 && (type == 'ppt' || type == 'word')) {
$(uploadObj).attr('data',responseMessage['data'])
$('#' + idName).append(responseMessage['msg'])
} else if (responseMessage['code'] == 1 && type == 'avatar') {
$('#' + idName).css('display', 'block');
$('#' + idName).attr('src',responseMessage['data'])
}
}
if(type == 'ppt' || type == 'word') {
var progress;
var progressObj = document.getElementById(idName);
if(total_blob_num == 1){
progress = '100%';
}else{
progress = Math.min(100,(blob_num/total_blob_num)* 100 ) +'%';
}
progressObj.style.width = progress;
}
var t = setTimeout(function(){
if(start < file.size && is_stop === 0){
blob = cutFile(file);
sendFile(blob,file,idName,uploadObj,type);
blob_num += 1;
}else{
setTimeout(t);
}
},1000);
}
xhr.send(form_data);
}
}
php
:
public function upload()
{
$file = $_FILES['file'];
$blobNum = $_POST['blob_num'];
$totalBlobNum = $_POST['total_blob_num'];
$fileName = $_POST['file_name'];
$fileType = $_POST['file_type'];
$fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
$tempName = $_FILES['file']['tmp_name']; //臨時檔案的絕對路徑
$pathPrefix = './Upload/' . $fileType;
if(!file_exists($pathPrefix)) {
mkdir($pathPrefix,0777);
}
chmod($pathPrefix,0777);
$filePath = $pathPrefix . '/' . $fileName . '_' . $blobNum;
$result = move_uploaded_file($tempName,$filePath);
$renameResult = '';
if($blobNum == $totalBlobNum){
$blob = '';
for($i=1; $i<= $totalBlobNum; $i++){
$blob .= file_get_contents($pathPrefix . '/' . $fileName .'_' . $i);
}
file_put_contents($pathPrefix . '/' .$fileName,$blob);
//合併完刪除檔案塊
for($i=1; $i<= $totalBlobNum; $i++){
unlink($pathPrefix . '/' . $fileName .'_'.$i);
}
$newFileName = $pathPrefix . '/' . time() . '.' . $fileExtension;
$renameResult = rename($pathPrefix . '/' .$fileName,$newFileName);
}
$newFileName = substr($newFileName,1);
if ($renameResult){
return [
'code' => 1,
'msg' => 'upload success',
'data' => $newFileName
];
}else{
return [
'code' => 0,
'msg' => 'upload failed'
];
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結