關于大文件上傳 思路
使用js讀取form表單中選擇的file,計算文件md5值,并上傳md5值到服務端,檢查文件是否已上傳過(類似秒傳功能)
若文件未上傳過,按照其大小切成1MB大小的塊,小于1MB的不用切
用ajax異步提交切好的塊上傳至服務端(一個塊一個請求,不阻塞,多線程)
當上傳完成所有切塊,發起一個合并文件的請求,服務端進行前面上傳的文件塊的合并,合并完成即上傳完成。
實現js計算文件md5使用spark-md5.js,據說這個庫使用的是世界上最快的md5算法。
js對文件切片并使用ajax上傳切片:
let size = file.size; //獲取文件大小 const shardSize = 1024 * 1024; // 塊大小1MB let shardCount = Math.ceil(size/shardSize); //可切成的塊數 for(let i = 0; i < shardCount; i++){ let start = i * shardSize, end = Math.min(size, start + shardSize); let form = new FormData(); form.append("file", file.slice(start, end)); //用slice方法切片 form.append("size", end - start); form.append("name", name); form.append("total", shardCount); form.append("md5", file_md5); //文件md5值 form.append("index", i); //第幾塊 $.ajax({ url: "upload.php?type=shard", type: "POST", data: form, // async: false, //是否異步上傳,默認true processData: false, //很重要,告訴jquery不要對form進行處理 contentType: false, //很重要,指定為false才能形成正確的Content-Type success: function (res) { // 成功回調 } } }
php端保存切片
$path = __DIR__ . "/uploads"; $file = $_FILES["file"]; $total = $_POST["total"]; $index = $_POST["index"]; $size = $_POST["size"]; $dst_file = $path . "/" . $name . "-" . $total . ":" . $index; // 切片文件存儲的文件名 if ($file["error"] > 0) { echo json_encode(["code"=>400, "msg"=>$file["error"]]);die; } else { $res = move_uploaded_file($file["tmp_name"], $dst_file); if ($res) { file_put_contents($dst_file . ".info", $size); // 切片上傳成功,寫一個保存其大小的文件,后續合并是校驗文件用的到 echo json_encode(["code"=>200, "msg"=>"shard ok"]);die; } else { echo json_encode(["code"=>400, "msg"=>"shard move_uploaded_file error"]);die; } }
php端合并
function mergeFile($name, $total, &$msg) { // 校驗切片文件是否都上傳完成,是否完整 for ($i = 0; $i < $total; $i++) { if (!file_exists($name . "-" . $total . ":" . $i . ".info") || !file_exists($name . "-" . $total . ":" . $i)) { $msg = "shard error $i"; return false; } else if (filesize($name . "-" . $total . ":" . $i) != file_get_contents($name . "-" . $total . ":" . $i . ".info")) { $msg = "shard size error $i"; return false; } } @unlink($name); if (file_exists($name . ".lock")) { //加鎖 防止有其他進程寫文件,造成文件損壞 $msg = "on lock"; return false; } touch($name . ".lock"); $file = fopen($name, "a+"); for ($i = 0; $i < $total; $i++) { //按切片順序寫入文件 $shardFile = fopen($name . "-" . $total . ":" . $i, "r"); $shardData = fread($shardFile, filesize($name . "-" . $total . ":" . $i)); fwrite($file, $shardData); fclose($shardFile); unlink($name . "-" . $total . ":" . $i); unlink($name . "-" . $total . ":" . $i . ".info"); } fclose($file); unlink($name . ".lock"); return true; }
我也寫好了一個demo,傳送門
下面是這個demo的效果圖:
這個demo有些方面還不夠完善,后續持續完善吧~
原文連接:
關于大文件上傳
更多分享知識點,請掃碼關注微信公眾號:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109785.html
摘要:,在后續測試時遇到一個詭異,當文件過大時,任務腳本上傳到七牛云失敗。當我遇到大文件無法上傳到七牛云時,斷點調試到這里,發現返回的是。后來還真被我找到了,七牛云官方提供一個腳本工具。 業務場景 需求 我們項目有一個文件上傳需求,需要從客戶端上傳到七牛云的對象存儲和自己的應用服務器上。這里使用七牛云主要是實現下載分發。應用服務器需要留一份是因為后續需要做文件分析(并且是上傳后需要立馬分析出...
摘要:數據遷移過程中的速率問題。關閉源站數據遷移典型案例剖析七牛客戶陌陌的數據量非常大,如果采用常用的傳輸辦法,整個遷移過程要耗時半年,并且會嚴重影響線上的業務。為此,七牛為陌陌制定了個性化的數據遷移方案。 showImg(http://sharlyne-lee.qiniudn.com/m1.png); 無論是計劃擁抱云服務還是打算從正在使用的云服務切換到另外一家,這其中數據的遷移是很關鍵...
摘要:沒有瀏覽器測試,所以不知道是不是有效,其實里面看起來比我寫的那個復雜,實際上多了個檢驗格式上兼容寫法所以不要怕,如果我錯了記得提醒下我啊。目前為止其實已經該說的都差不多覆蓋到了吧,動手能力強的話已經可以根據教程寫一個實例出來的了。 系列文章 關于前端上傳文件全面基礎掃盲貼(零)關于前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest關于前端上傳文件全面基礎掃盲貼(...
摘要:文章出處最近項目中有一個文件上傳的功能,可以上傳壓縮包文件,遇到一個問題,就是個別電腦點擊上傳控件時,需要四五秒左右才會有反應。由于我們請求不到海外服務器,會等到連接誒失敗,才會彈出上傳文件窗口。 文章出處:http://www.jianshu.com/p/be34... 最近項目中有一個文件上傳的功能,可以上傳壓縮包文件,遇到一個問題,就是個別電腦點擊上傳控件時,需要四五秒左右才會有...
閱讀 2581·2021-11-22 12:01
閱讀 1105·2021-11-15 11:37
閱讀 3685·2021-09-22 14:59
閱讀 1746·2021-09-04 16:45
閱讀 1382·2021-09-03 10:30
閱讀 1013·2021-08-11 11:18
閱讀 2459·2019-08-30 10:53
閱讀 2013·2019-08-29 15:13