日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

PHP+ajax大文件分片上傳示例代碼


PHP在上傳超大的文件時,不能只讓后端php上傳,會容易上傳到一半內測益處失效。需要前端要和后端相互配合一起來處理,文件上傳要使用AJAX的方法,而不是form的submit的方式。

前端把file文件對象按一定的大小分割成一定大小的文件(如按2M或5M來分割),對分割后的文件,一個個的上傳到后端去,后端接收到分片文件后,把它們先放到一個臨時的目錄下,在收到前端完成的數據請求的時候,把臨時目錄中的文件組裝起來成一個新的文件,保存后,把臨時目錄下的文件刪除掉就可以了。

示例代碼

HTML代碼:

<div class="a">
    上傳<input id="myfile" type="file" name="myfile"/>
</div>

這里要說明一下,沒有使用 submit 上傳,使用 ajax上傳。

JS代碼:

<script>
$(function(){
    let myfile = document.getElementById("myfile");
    myfile.onchange = function(){
        let file = myfile.files[0]; // 這里可以得到上傳的文件對象
        let length = 1024 * 1024 * 5; // 這里是每一個分片的大小
        let total_number = Math.ceil(file.size/length); // 使用進一法,來確定分片的個數
        let start = 0; // 分片的初始位置
        let end = length; // 分片的結束位置
        let parr = []; // 這里為promise.all方法準備一個數組
        for(let i = 1;i<=total_number;i++){
            // 這里開始分片,并且把每一個分片上傳到服務器
            let bolb = file.slice(start,end); // 得到一個分片
            start = end; // 調整下一個分片的起始位置
            end = start+length; // 調整下一個分片的結束位置
            if(end > file.size){
                end=file.size; // 這里對最后的一個分片結束位置進行調整
            }
            let formdata = new FormData(); // 創建一個FormData對象,準備傳送數據
            formdata.append("file",blob); // 將分片數據放入formdata
            formdata.append("tempfilename",i+"_"+file.name); // 同時為這個分片設置一個名稱,其中的i幫助后端進行排序處理
            // formdata組裝好之后,調用pro()函數,返回一個promise對象,并把它放入parr數組中,方便后面的promise.all方法使用
            parr.push(pro(formadata));
        }
        // 以上for循環結束之后,parr數組中就全部是分片上傳的promise的對象了,此時我們使用promise.all方法,等待所有上傳都成功執行后,再向服務器發送一個請求,也就是上傳完成,讓服務器組裝分片的請求
        Promise.all(parr).then(res=>{
            if(res.length == parr.length){ // 如果返回成功的數組長度和parr的數組長度相等,說明分片全部上傳成功
            // 此時對上傳接口再次發送請求,同時把上傳的文件名帶上,方便后臺查找要組裝的分片文件名,因為是請求同一個上傳接口,所以我們還要傳一個flag=1表示這是一個數據組裝的請求
                $.ajax({
                    type:"post",
                    url:"http://xxx.com/index/upload/getupload",
                    data:{flag:1,filename:file.name}, // 這里flag=1表示上傳完成,請求組裝,filename表示要組成哪一組文件分片
                    success:function(res){
                        if(res.length == parr.length){
                            console.log(111);
                        }
                    },
                    fail: function () {
                        reject()
                    }
                })
            }
        })
    }
})
// 這個函數用來上傳分片文件,返回的是一個promise對象,方便后面使用promise.all還判斷所有分片是否是上傳成功的
// 這里要說明一下,$.post()是不可以上傳文件的,只能用$.ajax()并且要把contentType:false和processData:false帶上
function pro(formData){
    return new Promise((resolve,reject)=>{
        $.ajax({
            type:"post",
            url:"http://xxx.com/index/upload/getupload", // 后臺上傳文件的地址
            data:formData,
            contentType: false, // 這個不能少,ajax上傳文件是不能少的
            processData: false, // 這個不能少,ajax上傳文件必傳false
            success:function(res){
                resolve(res)
            },
            fail: function () {
                reject()
            }
        })
    })
}
</script>

以上就是前端的js核心部分,注釋基本就可以看懂了。

php代碼:

<?php
// tp5框架
public function getUpload(){
    $tempdir = APP_PATH."../public/tempdir"; // 這里分片的文件指定了一個臨時目錄,后面會用到
    $flag = input("flag",0); // 接收參數flag如果沒有這個參數就默認為0,如果flag=1,表示要組裝分片
    if($flag == 0){
        // 這里是上傳分片
        $file = request()->file("file"); // 接收到這個分片
        $tempfilename = input("tempfilename"); // 接收到這個分片的名稱,注意:這個名稱中含有排序信息
        if(!file_exists($tempdir)){
            mkdir($tempdir,0755,true); // 如果臨時目錄不存在,則創建一個臨時目錄
        }
        $fileinfo = $file->move($tempdir,$tmpfilename);
        if($fileinfo){ // 把分片的文件保存在了臨時目錄中,返回有點簡單,可以根據需求返回相應的數據
            return josn(['error'=>0]);
        }else{
            return json(['error'=>1]);
        }
    }elseif($flag == 1){
        // 如果flag為1表示,分片已上傳完成了
        $filename = input("filename");
        // 通過文件名的字符串匹配,找上所有的分片,返回一個文件路徑的數組
        $fileArr = glob($tempdir."/*".$filename);
        // 這里的*是一個通配符,將所有的文件名中包含的$filename的文件都找到
        // 說明一下,$fileArr中的數組的順序不是我們想要的,所以我們新建一個數組來整理一下順序
        $newfileArr = [];
        foreach($fileArr as $f){
            // js前端把文件的名稱前加了'序號+_',以下劃線來分開并把序號寫在key中
            $fileBaseName = basename($f); // $f是一個個的路徑,這里使用basename得到文件名
            $fileBaseNameSplit = explode("_", $fileBaseName); // 通過下劃線分割文件名
            $newfileArr[$fileBaseNameSplit[0]] = $f; // 構造了一個新的數組,其中數組的key就是順序號,數組的值就是分片文件的路徑
        }
        // 分片的序號和路徑都準備好了,就可以組裝了
        $num = count($newfileArr); // 得到的所有分片的個數,為后面使用for循環做準備
        // 開始使用for循環來組裝
        $newfilename = "new-".$filename; // 這里為組裝后的文件起一個名字
        for($i=1; $i<=$num; $i++){
            // 這里以追加的方式,把分片文件都寫入到了一個文件中
            file_put_contents($newfilename,file_get_contents($newfileArr[$i]),FILE_APPEND);
        }
        // ......
        // 刪除臨時文件中的分片文件,這里可以使用try catch來判斷是否有錯誤
        foreach($newfileArr as $fi){
            unlink($fi);
        }
        // 最后給前端返回保存的文件名就可以
    }
}

上面的方法,我本地測試上傳了一個 650M的文件,只用的 20秒的時間,沒有在服務器上測試過,大家可以按照這個方法試一下。


分享到:
標簽:PHP+ajax上傳 大文件分片上傳
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定