溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

php中怎么利用webuploader實現(xiàn)斷點續(xù)傳功能

發(fā)布時間:2021-08-09 17:21:12 來源:億速云 閱讀:235 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)php中怎么利用webuploader實現(xiàn)斷點續(xù)傳功能,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

  1. webuploaderthinkphp5

斷點續(xù)傳的思路:

    客戶端:

        1.獲取文件md5(MD5是文件唯一標(biāo)識,用來判斷是否存在此文件,并且用作分片的文件夾名)     2.將文件分片     3.驗證分片是否上傳過,上傳過直接跳過當(dāng)前分片     3.上傳分片到md5的文件夾(保存文件名建議按分片序號來,因為分片的順序很重要)     4.最后一個分片上傳完成后發(fā)送合并分片請求并由服務(wù)器返回文件信息

    服務(wù)端

        1.獲取md5文件夾下的文件數(shù)量并返回用作分片驗證     2.接收文件分片并保存到文件md5的文件夾,文件名稱使用分片序號:如0.mp4,1.mp4     3.合并分片時將md5文件夾下的所有文件按文件名順序提取并寫入到最終的文件內(nèi)     4.寫入完成獲取最終文件hash并判斷是否存在,存在則返回已存在文件,刪除當(dāng)前文件,不存在則寫入數(shù)據(jù)庫并返回文件信息

大體思路是這樣,實際還要加入許多驗證,比客戶端獲取到md5后馬上要驗證文件是否存在,存在就不上傳,直接使用文件信息,不存在則上傳分片上傳前也要驗證,不過分片的跳過規(guī)則需要注意,服務(wù)器只需要返回已有的分片數(shù)量,客戶端根據(jù)已有的分片和當(dāng)前分片索引即可判斷是否應(yīng)該跳過,因為分片是按順序上傳的,如:,服務(wù)端需要注意合并的時候順序不能亂,順序亂了就無法還原源文件,所以建議用分片索引作為文件名,獲取的時候直接按0,1,2這樣獲取就行了.

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

完整代碼如下:

客戶端:

var uploader;var fileMd5;var is_upload;var totalFiles;function initWebUploader() {    /***************************************************** 監(jiān)聽分塊上傳過程中的三個時間點 start ***********************************************************/    WebUploader.Uploader.register({        "before-send":"beforeSend",  //每個分片上傳前    },    {        //時間點2:如果有分塊上傳,則每個分塊上傳之前調(diào)用此函數(shù)        beforeSend:function(block){            var deferred = WebUploader.Deferred();            if(is_upload)//跳過到開始上傳的哪一個分片時            {                deferred.resolve();            }else if(totalFiles)//已經(jīng)獲取過文件數(shù)量則直接判斷是否跳過            {                //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因為分塊上傳下標(biāo)是由小到大                if (block.chunk > totalFiles - 1) {                    is_upload = true;                    deferred.resolve();                } else {                    //分塊存在,跳過                    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)為分塊存在,因為分塊上傳下標(biāo)是由小到大                        if (block.chunk > data.data - 1) {                            is_upload = true;                            deferred.resolve();                        } else {                            //分塊存在,跳過                            deferred.reject();                        }                    } else {                        is_upload = true;                        deferred.resolve();                    }                });            }            return deferred.promise();        }    });    /***************************************************** 監(jiān)聽分塊上傳過程中的三個時間點 end **************************************************************/    uploader = WebUploader.create({        // swf文件路徑        swf:  '{$maccms.path}static/webupload/Uploader.swf',        // 文件接收服務(wù)端。        server: '/api.php/upload/chunkUpload',        // 選擇文件的按鈕??蛇x。        // 內(nèi)部根據(jù)當(dāng)前運行是創(chuàng)建,可能是input元素,也可能是flash.        pick: '#name',        accept: {            title: 'Images',            extensions: 'mp4',        },        // 不壓縮image, 默認(rèn)如果是jpeg,文件上傳前會壓縮一把再上傳!        resize: false,        prepareNextFile:true,        chunked : true, // 分片處理        chunkSize : 5 * 1024 * 1024, // 每片50M,經(jīng)過測試,發(fā)現(xiàn)上傳1G左右的視頻大概每片50M速度比較快的,太大或者太小都對上傳效率有影響        chunkRetry : false,// 如果失敗,則不重試        threads:1,        formData:{guid:WebUploader.Base.guid()}    });    uploader.on('fileQueued',function (file) {        uploader.md5File( file,0,10*1024*1024 )        // 及時顯示進度        .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);            //驗證文件是否存在            $.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=vod_play_url]").val(data.data.path);                    $(".file-address input[name=url_id]").val(data.data.id);                    //獲取視頻時長,配合video標(biāo)簽                    $("#duration").attr("src",data.data.path);                }            });        });    });    // 文件上傳過程中創(chuàng)建進度條實時顯示。    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 ) {        //最后一塊完成時間        //全部上傳完成發(fā)送合并請求        $.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=vod_play_url]").val(data.data.path);                $(".file-address input[name=url_id]").val(data.data.id);                $("#duration").attr("src",data.data.path);            }else{                (".up-end h2").text('上傳出錯');                $('.up-end').show();                $('.up-state').hide();                setTimeout(function () {                    $(".up-end").hide();                    $('.up-con').show();                },2000);            }        });    });    uploader.on( 'uploadError', function( file ) {        $(".up-end h2").text('上傳出錯');        $('.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;            }            //合并后的文件入庫并返回            $_data = ['name' => $file_name, 'path' => $path_file, '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;    }}//分片驗證function checkChunk(){    $md5 = request()->param()['md5'];    $dir = PATH_FILE . $md5;    if(is_dir($dir)) {        $files = $this->getFileByPath($dir);        return count($files);    }else{        return false;    }}

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

//時間點2:如果有分塊上傳,則每個分塊上傳之前調(diào)用此函數(shù)beforeSend:function(block){    var deferred = WebUploader.Deferred();    if(is_upload)//跳過到開始上傳的哪一個分片時    {        deferred.resolve();    }else if(totalFiles)//已經(jīng)獲取過文件數(shù)量則直接判斷是否跳過    {        //當(dāng)前分片下標(biāo)小于等于目錄下的文件數(shù)量就認(rèn)為分塊存在,因為分塊上傳下標(biāo)是由小到大        if (!totalFiles.in_array(block.chunk)) {            deferred.resolve();        } else {            //分塊存在,跳過            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)為分塊存在,因為分塊上傳下標(biāo)是由小到大                if (!data.data.in_array(block.chunk)) {                    deferred.resolve();                } else {                    //分塊存在,跳過                    deferred.reject();                }            } else {                is_upload = true;                deferred.resolve();            }        });    }    return deferred.promise();

后端:

//分片驗證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($file_name) - 1];            $file_index = explode('.',$file_name)[0];            $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;};

以上就是php中怎么利用webuploader實現(xiàn)斷點續(xù)傳功能,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI