PHP+JS大文件切割异步上传

用到的PHP文件系统函数

bool move_uploaded_file ( string destination ) 将上传的文件移动到新位置

bool file_exists ( string $filename ) 检查文件或目录是否存在。

[resource fopen ( string mode [, bool context ]] )](http://php.net/manual/zh/function.fopen.php) 打开文件或者 URL

int filesize ( string $filename ) 取得文件大小

string fread ( resource length ) 读取文件(可安全用于二进制文件)

int fwrite ( resource string [, int $length ] )写入文件(可安全用于二进制文件)

bool fclose ( resource $handle ) 关闭一个已打开的文件指针

[bool unlink ( string context ] )](http://php.net/manual/zh/function.unlink.php) 删除文件

[string md5_file ( string raw_output = FALSE ] )](http://php.net/manual/zh/function.md5-file.php) 计算指定文件的 MD5 散列值


upload.html


上传App


upload.js


function onchangeUpload(obj,progress_id,self_id)

{

    var blob= obj.files[0];

    browserMD5File(blob, function (err, md5) {

        //console.log(md5); // 97027eb624f85892c69c4bcec8ab0f11

        var time= Math.floor((new Date().valueOf())/ 1000);

        var bytesPerPiece= 1024 * 1024 * 2; // 文件切片大小定义.

        var totalPieces;

        var x= 4, y= 0;

        var rand= '';

        for (var i= 0; i< 5; i++) {

            rand+= parseInt(Math.random()* (x- y+ 1)+ y);

        }

        var start= 0;

        var end;

        var index= 1;

        var filesize= blob.size;

        var filename= time+ rand+ '.apk';

        var that= obj;

        //计算文件切片总数

        totalPieces= Math.ceil(filesize/ bytesPerPiece);

        var progress;

        var progressObj= document.getElementById(progress_id);

        //重新上传则清空进度条

        progress= '0%';

        progressObj.style.width= progress;

        var upload_status= true;

        while(start< filesize)

        {

             end= start+ bytesPerPiece;

            if (end> filesize) {

                  end= filesize;

            }

            var chunk= blob.slice(start, end);//切割文件

            // 兼容firefox

            /*if(blob.mozSlice){

            var chunk =  blob.mozSlice(startByte,endByte);

            }*/

            //传参

            var formData= new FormData();

            formData.append("file", chunk, filename+ index);

            formData.append("file_name", filename);

            formData.append("total_pieces", totalPieces);

            formData.append("now_pieces", index);

            formData.append("md5", md5);

            $.ajax({

                url: './asyncUploadAjax',

                type: 'POST',

                cache: false,

                data: formData,

                processData: false,

                contentType: false,

                async: true // true:异步,false:同步

            }).done(function (res) {

                if (JSON.parse(res).code== 1) {

                    progress= Math.min(100, ((JSON.parse(res).n+1)/ totalPieces)* 100)+ '%';

                    progressObj.style.width= progress;

                }else if (JSON.parse(res).code== 2) {

                    //判断是否有上传失败的节点

                    if(upload_status== true)

                    {

                        progress= '100%';

                        progressObj.style.width= progress;

                        document.getElementById(that.name).value= JSON.parse(res).file_path;

                        //清空file  防止将文件大小计算到表单里

                        document.getElementById(self_id).innerHTML= '';

                        alert(blob.name+ ' 上传完成');

                    }else{

                         alert(blob.name+ JSON.parse(res).msg);

                    }

                }else {

                      upload_status= false;

                }

            }).fail(function (res) {

                  upload_status= false;

            });

            start= end;

            index++;

        }

})

}


spark-md5.js


upload.php


/*

    * 异步上传

    * */

    public function asyncUploadAjax()

    {

        $data['code'] = 1;

        $data['msg'] = 'waiting for all';

        $data['file_path'] = '';

        $form_data = $_POST;

        $file = $_FILES;

        $new_file_path = $_SERVER['SINASRV_DATA_DIR'].'/'. $_FILES['file']['name'];

        if (move_uploaded_file($file['file']['tmp_name'], $new_file_path)) {

            //判断是否上传完成

            $status = self::checkUploadAccomplish($form_data['file_name'], $form_data['total_pieces']);

            if($status['status'])

            {

                //合并切片文件

                $file_path = self::mergeSlices($form_data['file_name'], $form_data['total_pieces']);

                //验证文件安全

                if(md5_file($file_path) == $form_data['md5'])

                {

                    $data['code'] = 2;

                    $data['msg'] = 'upload success';

                    $data['file_path'] = $file_path;

                }else{

                    $data['code'] = 0;

                    $data['msg'] = '文件不安全,请重新上传';

                }

            }else{

                $data['n'] = $status['n'];

            }

        } else {

            $data['code'] = 0;

            $data['msg'] = 'upload fail';

        }

        echo json_encode($data);

    }

    /*

    * 判断文件是否上传完成

    * */

    public function checkUploadAccomplish($file_name='', $total_pieces)

    {

        $file_name = substr($file_name, 0, 15);

        $n = 0;

        $status = true;

        for($i=1; $i<=$total_pieces; $i++)

        {

            if(!file_exists($_SERVER['SINASRV_DATA_DIR'].'/'. $file_name.'.apk'.$i))

            {

                $status = false;

            }else{

                $n++;

            }

        }

        return ['n'=>$n, 'status'=>$status];

    }

    /*

    * 合并切片文件

    * */

    public function mergeSlices($file_name='', $total_pieces)

    {

        $file_name = substr($file_name, 0, 15);

        $new_file_name = $_SERVER['SINASRV_DATA_DIR'].'/'.$file_name.'.apk';

        $fp = fopen($new_file_name,"wb");

        for($i=1; $i<=$total_pieces; $i++)

        {

            $tmp_name = $_SERVER['SINASRV_DATA_DIR'].'/'. $file_name.'.apk'.$i;

            //只读方式打开文件 指针指向文件头

            $handle = fopen($tmp_name,"rb");

            //切片文件写入新文件

            fwrite($fp,fread($handle,filesize($tmp_name)));

            //关闭切片文件

            fclose($handle);

            unset($handle);

            //删除切片

            unlink($tmp_name);

        }

        fclose($fp);

        return $new_file_name;

    }

你可能感兴趣的:(PHP+JS大文件切割异步上传)