最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

php結(jié)合webuploader斷點(diǎn)續(xù)傳的實(shí)現(xiàn)

2023-10-27 12:18 作者:限量版范兒  | 我要投稿

最近公司項(xiàng)目需要用到斷點(diǎn)續(xù)傳,所以記錄一下其中的坑
使用到的主要技術(shù)

webuploader
thinkphp5
斷點(diǎn)續(xù)傳的思路:

客戶(hù)端:

? ? ?1.獲取文件md5(MD5是文件唯一標(biāo)識(shí),用來(lái)判斷是否存在此文件,并且用作分片的文件夾名)

? ? ?2.將文件分片

? ? ?3.驗(yàn)證分片是否上傳過(guò),上傳過(guò)直接跳過(guò)當(dāng)前分片

? ? ?3.上傳分片到md5的文件夾(保存文件名建議按分片序號(hào)來(lái),因?yàn)榉制捻樞蚝苤匾?

? ? ?4.最后一個(gè)分片上傳完成后發(fā)送合并分片請(qǐng)求并由服務(wù)器返回文件信息

服務(wù)端

? ? ?1.獲取md5文件夾下的文件數(shù)量并返回用作分片驗(yàn)證

? ? ?2.接收文件分片并保存到文件md5的文件夾,文件名稱(chēng)使用分片序號(hào):如0.mp4,1.mp4

? ? ?3.合并分片時(shí)將md5文件夾下的所有文件按文件名順序提取并寫(xiě)入到最終的文件內(nèi)

? ? ?4.寫(xiě)入完成獲取最終文件hash并判斷是否存在,存在則返回已存在文件,刪除當(dāng)前文件,不存在則寫(xiě)入數(shù)據(jù)庫(kù)并返回文件信息

大體思路是這樣,實(shí)際還要加入許多驗(yàn)證,比客戶(hù)端獲取到md5后馬上要驗(yàn)證文件是否存在,存在就不上傳,直接使用文件信息,不存在則上傳
分片上傳前也要驗(yàn)證,不過(guò)分片的跳過(guò)規(guī)則需要注意,服務(wù)器只需要返回已有的分片數(shù)量,客戶(hù)端根據(jù)已有的分片和當(dāng)前分片索引即可判斷是否應(yīng)該跳過(guò),因?yàn)榉制前错樞蛏蟼鞯?如:

,服務(wù)端需要注意合并的時(shí)候順序不能亂,順序亂了就無(wú)法還原源文件,所以建議用分片索引作為文件名,獲取的時(shí)候直接按0,1,2這樣獲取就行了.

并且保存時(shí)要注意保存在自定義的目錄下需要確保該目錄存在,不存在的目錄需要新建后才可以保存文件

完整代碼如下:

客戶(hù)端:

var uploader;
var fileMd5;
var is_upload;
var totalFiles;
function initWebUploader() {
? ? /***************************************************** 監(jiān)聽(tīng)分塊上傳過(guò)程中的三個(gè)時(shí)間點(diǎn) start ***********************************************************/
? ? WebUploader.Uploader.register({
? ? ? ? "before-send":"beforeSend", ?//每個(gè)分片上傳前
? ? },
? ? {
? ? ? ? //時(shí)間點(diǎn)2:如果有分塊上傳,則每個(gè)分塊上傳之前調(diào)用此函數(shù)
? ? ? ? beforeSend:function(block){
? ? ? ? ? ? var deferred = WebUploader.Deferred();
? ? ? ? ? ? if(is_upload)//跳過(guò)到開(kāi)始上傳的哪一個(gè)分片時(shí)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? }else if(totalFiles)//已經(jīng)獲取過(guò)文件數(shù)量則直接判斷是否跳過(guò)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因?yàn)榉謮K上傳下標(biāo)是由小到大
? ? ? ? ? ? ? ? if (block.chunk > totalFiles - 1) {
? ? ? ? ? ? ? ? ? ? is_upload = true;
? ? ? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? //分塊存在,跳過(guò)
? ? ? ? ? ? ? ? ? ? deferred.reject();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? $.post('/api.php/upload/checkUpload', {md5: fileMd5}, function (data) {
? ? ? ? ? ? ? ? ? ? if (data.code) {
? ? ? ? ? ? ? ? ? ? ? ? totalFiles = data.data;
? ? ? ? ? ? ? ? ? ? ? ? //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因?yàn)榉謮K上傳下標(biāo)是由小到大
? ? ? ? ? ? ? ? ? ? ? ? if (block.chunk > data.data - 1) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? is_upload = true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? //分塊存在,跳過(guò)
? ? ? ? ? ? ? ? ? ? ? ? ? ? deferred.reject();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? is_upload = true;
? ? ? ? ? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }
? ? ? ? ? ? return deferred.promise();
? ? ? ? }
? ? });
? ? /***************************************************** 監(jiān)聽(tīng)分塊上傳過(guò)程中的三個(gè)時(shí)間點(diǎn) end **************************************************************/
? ? uploader = WebUploader.create({
? ? ? ? // swf文件路徑
? ? ? ? swf: ?'{$maccms.path}static/webupload/Uploader.swf',
? ? ? ? // 文件接收服務(wù)端。
? ? ? ? server: '/api.php/upload/chunkUpload',
? ? ? ? // 選擇文件的按鈕。可選。
? ? ? ? // 內(nèi)部根據(jù)當(dāng)前運(yùn)行是創(chuàng)建,可能是input元素,也可能是flash.
? ? ? ? pick: '#name',
? ? ? ? accept: {
? ? ? ? ? ? title: 'Images',
? ? ? ? ? ? extensions: 'mp4',
? ? ? ? },
? ? ? ? // 不壓縮image, 默認(rèn)如果是jpeg,文件上傳前會(huì)壓縮一把再上傳!
? ? ? ? resize: false,
? ? ? ? prepareNextFile:true,
? ? ? ? chunked : true, // 分片處理
? ? ? ? chunkSize : 5 * 1024 * 1024, // 每片50M,經(jīng)過(guò)測(cè)試,發(fā)現(xiàn)上傳1G左右的視頻大概每片50M速度比較快的,太大或者太小都對(duì)上傳效率有影響
? ? ? ? chunkRetry : false,// 如果失敗,則不重試
? ? ? ? threads:1,
? ? ? ? formData:{guid:WebUploader.Base.guid()}
? ? });
? ? uploader.on('fileQueued',function (file) {
? ? ? ? uploader.md5File( file,0,10*1024*1024 )
? ? ? ? // 及時(shí)顯示進(jìn)度
? ? ? ? .progress(function(percentage) {
? ? ? ? ? ? console.log('Percentage:', percentage);
? ? ? ? ? ? $(".readFile").text("正在讀取視頻信息..."+(percentage * 100).toFixed(2) + '%');
? ? ? ? })
? ? ? ? // 完成
? ? ? ? .then(function(val) {
? ? ? ? ? ? console.log('md5 result:', val);
? ? ? ? ? ? $(".readFile").text('');
? ? ? ? ? ? fileMd5 = val;
? ? ? ? ? ? var formData = uploader.option('formData');
? ? ? ? ? ? formData.md5 = val;
? ? ? ? ? ? uploader.option('formData',formData);
? ? ? ? ? ? //驗(yàn)證文件是否存在
? ? ? ? ? ? $.post('/api.php/upload/md5check',{md5:val},function (data) {
? ? ? ? ? ? ? ? if(data.code)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //選擇后直接上傳
? ? ? ? ? ? ? ? ? ? uploader.upload();
? ? ? ? ? ? ? ? ? ? $("#name .webuploader-pick").text(file.name);
? ? ? ? ? ? ? ? ? ? $(".up-state .file_name").text(file.name);
? ? ? ? ? ? ? ? ? ? var size;
? ? ? ? ? ? ? ? ? ? size = Math.round(file.size/(1024*1024),2);
? ? ? ? ? ? ? ? ? ? if(size > 1024)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? size = Math.round(size/1024,2) + 'G';
? ? ? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? ? ? size += 'M';
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? $(".up-state .file_size").text(size);
? ? ? ? ? ? ? ? ? ? $('.up-in').width('0');
? ? ? ? ? ? ? ? ? ? $('.bar').find('span').html('0%');
? ? ? ? ? ? ? ? ? ? $('.up-con').hide();
? ? ? ? ? ? ? ? ? ? $('.up-state').show();
? ? ? ? ? ? ? ? ? ? $('#go').click(function () {
? ? ? ? ? ? ? ? ? ? ? ? $('.up-end').hide();
? ? ? ? ? ? ? ? ? ? ? ? $('.up-con').show();
? ? ? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? var msg = '該視頻已存在!';
? ? ? ? ? ? ? ? ? ? alert(msg);
? ? ? ? ? ? ? ? ? ? uploader.reset();
? ? ? ? ? ? ? ? ? ? $("#name .webuploader-pick").text(file.name);
? ? ? ? ? ? ? ? ? ? $(".up-state .file_name").text(file.name);
? ? ? ? ? ? ? ? ? ? $(".file-address input

name=vodplayurl

").val(data.data.path);
? ? ? ? ? ? ? ? ? ? $(".file-address input

name=urlid

").val(data.data.id);
? ? ? ? ? ? ? ? ? ? //獲取視頻時(shí)長(zhǎng),配合video標(biāo)簽
? ? ? ? ? ? ? ? ? ? $("#duration").attr("src",data.data.path);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? });
? ? });
? ? // 文件上傳過(guò)程中創(chuàng)建進(jìn)度條實(shí)時(shí)顯示。
? ? uploader.on( 'uploadProgress', function( file, percentage ) {
? ? ? ? $('.bar').find('span').html((percentage * 100).toFixed(2) + '%');
? ? ? ? $('.up-in').width(percentage * 100 + '%');
? ? });
? ? uploader.on( 'uploadSuccess', function( file,res ) {
? ? ? ? //最后一塊完成時(shí)間
? ? ? ? //全部上傳完成發(fā)送合并請(qǐng)求
? ? ? ? $.post('/api.php/upload/videoUpload',{md5:fileMd5},function (data) {
? ? ? ? ? ? if(data.code)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? $('.up-end').show();
? ? ? ? ? ? ? ? $('.up-state').hide();
? ? ? ? ? ? ? ? setTimeout(function () {
? ? ? ? ? ? ? ? ? ? $(".up-end").hide();
? ? ? ? ? ? ? ? ? ? $('.up-con').show();
? ? ? ? ? ? ? ? },2000);
? ? ? ? ? ? ? ? $(".file-address input

name=vodplayurl

").val(data.data.path);
? ? ? ? ? ? ? ? $(".file-address input

name=urlid

").val(data.data.id);
? ? ? ? ? ? ? ? $("#duration").attr("src",data.data.path);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? (".up-end h1").text('上傳出錯(cuò)');
? ? ? ? ? ? ? ? $('.up-end').show();
? ? ? ? ? ? ? ? $('.up-state').hide();
? ? ? ? ? ? ? ? setTimeout(function () {
? ? ? ? ? ? ? ? ? ? $(".up-end").hide();
? ? ? ? ? ? ? ? ? ? $('.up-con').show();
? ? ? ? ? ? ? ? },2000);
? ? ? ? ? ? }
? ? ? ? });
? ? });
? ? uploader.on( 'uploadError', function( file ) {
? ? ? ? $(".up-end h1").text('上傳出錯(cuò)');
? ? ? ? $('.up-end').show();
? ? ? ? $('.up-state').hide();
? ? ? ? setTimeout(function () {
? ? ? ? ? ? $(".up-end").hide();
? ? ? ? ? ? $('.up-con').show();
? ? ? ? },2000);
? ? });
}

服務(wù)器:

?

//分片上傳
function chunkUpload($name = 'file')
{
? ? $md5 = request()->param()

md5

;
? ? $object_info = request()->file($name);
? ? //保存文件的順序很重要!
? ? $object = $object_info->rule('uniqid')->move(PATH_FILE . $md5 . '/',request()->param()

chunk

);
? ? if($object)
? ? {
? ? ? ?return

chunks=>request()?>param()\[chunks

,'chunk'=>request()->param()

chunk

\];
? ? }else{
? ? ? ? return false;
? ? }
}
//最終合并文件
function videoUpload()
{
? ? $md5 = request()->param()

md5

;
? ? $dir = PATH_FILE . $md5;
? ? if(is_dir($dir)) {
? ? ? ? //獲取文件的順序很重要!!!
? ? ? ? $files =

?

;
? ? ? ? $chunk_id = 0;
? ? ? ? $chunk_file = PATH_FILE . $md5 . '/';
? ? ? ? while (file_exists($chunk_file . $chunk_id . '.mp4')){
? ? ? ? ? ? $files

?

= $chunk_file . $chunk_id . '.mp4';
? ? ? ? ? ? $chunk_id++;
? ? ? ? }
? ? ? ? $file_name = randomStr().'.mp4';
? ? ? ? $path_file = date('Ymd') . SYS_DS_PROS . $file_name;
? ? ? ? //日期目錄不存在則創(chuàng)建目錄
? ? ? ? if(!is_dir(PATH_FILE . date('Ymd')))
? ? ? ? {
? ? ? ? ? ? mkdir(PATH_FILE . date('Ymd'));
? ? ? ? }
? ? ? ? $count = 0;
? ? ? ? foreach ($files as $v)
? ? ? ? {
? ? ? ? ? ? $_file = file_get_contents($v);
? ? ? ? ? ? $_res = file_put_contents(PATH_FILE . $path_file,$_file,FILE_APPEND);
? ? ? ? ? ? if($_res)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? unlink($v);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? $count++;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if($count == 0)
? ? ? ? {
? ? ? ? ? ? rmdir($dir);
? ? ? ? ? ? //檢查合并后的文件hash
? ? ? ? ? ? $_hash = hash_file('sha1', PATH_FILE . $path_file);
? ? ? ? ? ? //合并后的文件已存在則刪除已合并文件并返回已有文件信息
? ? ? ? ? ? $file_info = $this->modelFile->getInfo(

sha1=>$hash

,'id,name,path,sha1,guid,md5');
? ? ? ? ? ? if(!empty($file_info))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? unlink(PATH_FILE . $path_file);
? ? ? ? ? ? ? ? return $file_info;
? ? ? ? ? ? }
? ? ? ? ? ? //合并后的文件入庫(kù)并返回
? ? ? ? ? ? $_data =

name=>$filename,path=>$pathfile,sha1=>$hash,guid=>′′,md5=>request()?>param()\[md5

\];
? ? ? ? ? ? $result = $this->modelFile->addInfo($_data);
? ? ? ? ? ? $_data

id

= $result;
? ? ? ? ? ? return $_data;
? ? ? ? }else{
? ? ? ? ? ? $this->error = '合并文件失敗';
? ? ? ? ? ? return false;
? ? ? ? }
? ? }else{
? ? ? ? $this->error = '分片目錄不存在!';
? ? ? ? return false;
? ? }
}
//分片驗(yàn)證
function checkChunk()
{
? ? $md5 = request()->param()

md5

;
? ? $dir = PATH_FILE . $md5;
? ? if(is_dir($dir)) {
? ? ? ? $files = $this->getFileByPath($dir);
? ? ? ? return count($files);
? ? }else{
? ? ? ? return false;
? ? }
}

?


=========================================================================
最新更新:
分片驗(yàn)證存在bug,當(dāng)上傳分片不小心刪除了前面的分片時(shí)就導(dǎo)致無(wú)法合成文件(文件數(shù)量導(dǎo)致跳過(guò)了),因此,更新分片驗(yàn)證
前端:

//時(shí)間點(diǎn)2:如果有分塊上傳,則每個(gè)分塊上傳之前調(diào)用此函數(shù)
beforeSend:function(block){
? ? var deferred = WebUploader.Deferred();
? ? if(is_upload)//跳過(guò)到開(kāi)始上傳的哪一個(gè)分片時(shí)
? ? {
? ? ? ? deferred.resolve();
? ? }else if(totalFiles)//已經(jīng)獲取過(guò)文件數(shù)量則直接判斷是否跳過(guò)
? ? {
? ? ? ? //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因?yàn)榉謮K上傳下標(biāo)是由小到大
? ? ? ? if (!totalFiles.in_array(block.chunk)) {
? ? ? ? ? ? deferred.resolve();
? ? ? ? } else {
? ? ? ? ? ? //分塊存在,跳過(guò)
? ? ? ? ? ? deferred.reject();
? ? ? ? }
? ? } else {
? ? ? ? $.post('/api.php/upload/checkUpload', {md5: fileMd5}, function (data) {
? ? ? ? ? ? if (data.code) {
? ? ? ? ? ? ? ? totalFiles = data.data;
? ? ? ? ? ? ? ? //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因?yàn)榉謮K上傳下標(biāo)是由小到大
? ? ? ? ? ? ? ? if (!data.data.in_array(block.chunk)) {
? ? ? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? //分塊存在,跳過(guò)
? ? ? ? ? ? ? ? ? ? deferred.reject();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? is_upload = true;
? ? ? ? ? ? ? ? deferred.resolve();
? ? ? ? ? ? }
? ? ? ? });
? ? }
? ? return deferred.promise();

后端:

//分片驗(yàn)證
public function checkChunk()
{
? ? $md5 = request()->param()

md5

;
? ? $dir = PATH_FILE . $md5;
? ? if(is_dir($dir)) {
? ? ? ? $files = $this->getFileByPath($dir);
? ? ? ? foreach ($files as $k=>$v)
? ? ? ? {
? ? ? ? ? ? $file_name = explode('/',$v);
? ? ? ? ? ? $file_name = $file_name

count($filename)?1

;
? ? ? ? ? ? $file_index = explode('.',$file_name)

00

;
? ? ? ? ? ? $files

$k

= (int)$file_index;
? ? ? ? }
? ? ? ? return $files;
? ? }else{
? ? ? ? return false;
? ? }
}

利用文件名的有序性判斷當(dāng)前分片索引是否存在服務(wù)器
判斷是否存在數(shù)組中的函數(shù):

?

Array.prototype.in_array = function (element) {
? ? for (var i = 0; i < this.length; i++) {
? ? ? ? if (this

i

== element) {
? ? ? ? ? ? return true;
? ? ? ? }
? ? } return false;
};

轉(zhuǎn)自鏈接:www.npqdlp.com

php結(jié)合webuploader斷點(diǎn)續(xù)傳的實(shí)現(xiàn)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
苏尼特右旗| 大宁县| 青铜峡市| 郴州市| 南雄市| 忻城县| 平阴县| 石首市| 荆州市| 平潭县| 曲水县| 崇左市| 惠安县| 苍溪县| 崇信县| 唐海县| 云南省| 巫山县| 泸水县| 遂平县| 日土县| 玉环县| 阿克| 清镇市| 汾西县| 腾冲县| 保康县| 左权县| 鲁山县| 郧西县| 望江县| 万州区| 西城区| 鄂尔多斯市| 宁乡县| 儋州市| 黔东| 龙里县| 万年县| 高雄市| 灵石县|