JS分片上传

JS分片上传

//分片上传

function ScarecrowPatchUpload (uploadPath, isPatch,onePackSize=1024*1024) {

    //是否分片上传

    isPatch = isPatch == undefined ? false : Boolean(isPatch);

    if (uploadPath == undefined) {

        throw new Error("ScarecrowPatchUpload obj must parameter 1:uploadPath");

    }

    this.__init__(uploadPath, isPatch, onePackSize);

}

ScarecrowPatchUpload.prototype={

    constructor: ScarecrowPatchUpload,

    fileObj:null,

    fileName:"",

    fileSize:0,

    uploadPath:"./",

    onePackSize:1024*1024*8,

    blockData:null,

    blockNum:0,

    blockNumSum:0,

    isPatch:false,

    startIndex:0,

    endIndex:0,

    formData:null,

    ajaxObj:null,

    isSend:false,

    isSendTemp:true,

    __iCnt:0,

    //上传完成回调函数

    funcUploadSuccess:function () {},

    //每个分片上传成功回调函数

    funcUploadStateChange:function () {},

    __init__:function (uploadPath, isPatch, onePackSize) {

        this.isPatch = isPatch;

        this.formData = new FormData();

        this.ajaxObj = new XMLHttpRequest();

        this.uploadPath = uploadPath;

        if (this.isPatch) {

            this.onePackSize = onePackSize;

        }

    },

    addFile:function (fileInfo) {

        if (fileInfo.files.length < 1) {

            console.error("没有找到对应的文件");

            return false;

        }

        console.log(fileInfo.files);

        this.fileObj = fileInfo.files[0];

        this.fileName = this.fileObj.name;

        this.fileSize = this.fileObj.size;

        if (this.isPatch) {

            this.blockNumSum = Math.ceil(this.fileSize / this.onePackSize)

        }

        this.isSend = true;

        this.isSendTemp = false;

        if (this.isPatch) {

            this.__iCnt = setInterval(()=>{

                console.log(this.blockNum);

                if (this.blockNum >= this.blockNumSum) {

                    clearInterval(this.__iCnt);

                    return ;

                }

                if (this.isSendTemp) {

                    this.sendFile();

                }

            }, 500);

        }

    },

    //发送文件

    sendFile:function () {

        this.isSendTemp = false;

        if (!this.isSend) {

            console.error("请先使用addFile添加文件对象");

            return false;

        }

        if (this.isPatch) {

            if(!this.cutFile()){

                return ;

            }

        } else {

            this.blockNum = 1;

            this.blockNumSum = 1;

            this.blockData = this.fileObj;

        }

        this.clearFormData();

        this.formData.append('file', this.blockData);

        this.formData.append('blockNum', this.blockNum);

        this.formData.append('blockNumSum', this.blockNumSum);

        this.formData.append('fileName', this.fileName);

        this.formData.append('isPatch', this.isPatch);

        this.ajaxObj.open('POST',this.uploadPath,false);

        this.ajaxObj.onreadystatechange =  () => {

            if (this.ajaxObj.status == 500 && this.isPatch) {

                clearInterval(this.__iCnt);

            }

            if (this.ajaxObj.readyState == 4 && this.ajaxObj.status == 200) {

                this.funcUploadStateChange.call(this);

                if (this.blockNum >= this.blockNumSum) {

                    this.funcUploadSuccess.call(this);

                    this.__resetObj();

                }

                this.ajaxObj.readyState = 1;

                this.isSendTemp = true;

            }

        }

        this.ajaxObj.send(this.formData);

    },

    //分割文件

    cutFile:function () {

        this.endIndex = this.startIndex + this.onePackSize;

        if (this.startIndex > this.fileSize) {

            this.startIndex = 0;

            return false;

        }

        this.blockNum += 1;

        this.blockData = this.fileObj.slice(this.startIndex, this.endIndex);

        this.startIndex = this.endIndex;

        return true;

    },

    clearFormData:function () {

        this.formData.has('file') ? this.formData.delete("file"): null;

        this.formData.has('blockNum') ? this.formData.delete("blockNum"): null;

        this.formData.has('blockNumSum') ? this.formData.delete("blockNumSum"): null;

        this.formData.has('fileName') ? this.formData.delete("fileName"): null;

        this.formData.has('isPatch') ? this.formData.delete("isPatch"): null;

    },

    setFuncUploadSuccess:function (func) {

        if (typeof func == "function") {

            this.funcUploadSuccess = func;

        } else {

            throw new Error("setFuncUploadSuccess parameter 1 must is function");

        }

    },

    //设置上传状态改变函数

    setFuncUploadStateChange:function (func) {

        if (typeof func == "function") {

            this.funcUploadStateChange = func;

        } else {

            throw new Error("setFuncUploadStateChange parameter 1 must is function");

        }

    },

    //重置参数

    __resetObj:function () {

        this.fileObj = null;

        this.blockNumSum = 0;

        this.blockNum = 0;

        this.endIndex = 0;

        this.formData = new FormData();

    }

}



文档:


## 分页上传JS说明文档

## 方法:

### addFile(fileInfo):void

    添加一个文件对象

    fileInfo为input 中的file具体对象


### sendFile():void

    上传文件

### setFuncUploadSuccess(func):void

    设置上传成功后的回调函数

    func:callback 回调函数


### setFuncUploadStateChange(func):void

    设置分片上传每个分片上传成功时的回调函数

    func:callback 回调函数   




示例:

index.html

<!doctype html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport"

          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title>

    <style>

        #progress{

            width: 300px;

            height: 20px;

            background-color:#f7f7f7;

            box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);

            border-radius:4px;

            background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);

        }

        #finish{

            background-color: #149bdf;

            background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);

            background-size:40px 40px;

            height: 100%;

        }

        form{

            margin-top: 50px;

        }

    </style>

</head>

<body>

<div id="progress">

    <div id="finish" style="width: 0%;" progress="0"></div>

    <br>

    <span id="showjindu"></span>

</div>

<form>

    <input type="file" name="file" id="file">

    <input type="button" value="上传" id="sc">

</form>

<script src="ScarecrowPatchUpload.js"></script>

<script>

    var fileForm = document.getElementById("file");

    upload = new ScarecrowPatchUpload("./index.php", true);

    upload.setFuncUploadSuccess(function () {

        console.log(this.fileName+"上传成功");

        alert(this.fileName+"上传成功");

    });

    upload.setFuncUploadStateChange(function () {

        var progress;

        var progressObj = document.getElementById('finish');

        var showjindu = document.getElementById("showjindu");

        if(this.blockNumSum == 1){

            progress = '100%';

        }else{

            progress = Math.min(100,(this.blockNum/this.blockNumSum)* 100 ) +'%';

        }

        progressObj.style.width = progress;

        showjindu.innerHTML= progress;

    });

    fileForm.onchange = function(){

        upload.addFile(this);

        upload.sendFile();

    }

</script>

</body>

</html>



upload.php

<?php

class Upload{

    private $filepath = './upload'; //上传目录

    private $tmpPath; //PHP文件临时目录

    private $blobNum; //第几个文件块

    private $totalBlobNum; //文件块总数

    private $fileName; //文件名

    public function __construct($tmpPath,$blobNum,$totalBlobNum,$fileName){

        $this->tmpPath = $tmpPath;

        $this->blobNum = $blobNum;

        $this->totalBlobNum = $totalBlobNum;

        $this->fileName = $fileName;

    }

    //判断是否是最后一块,如果是则进行文件合成并且删除文件块

    private function fileMerge(){

        if($this->blobNum == $this->totalBlobNum){

            $file = fopen($this->filepath.'/'. $this->fileName, "a+");

            $blob = '';

            for($i=1; $i<= $this->totalBlobNum; $i++){

                $blob = file_get_contents($this->filepath.'/'. $this->fileName.'__'.$i);

                fwrite($file, $blob);

            }

            fclose($file);

            $this->deleteFileBlob();

        }

    }

    //删除文件块

    private function deleteFileBlob(){

        for($i=1; $i<= $this->totalBlobNum; $i++){

            @unlink($this->filepath.'/'. $this->fileName.'__'.$i);

        }

    }

    //移动文件

    private function moveFile(){

        $this->touchDir();

        $filename = $this->filepath.'/'. $this->fileName.'__'.$this->blobNum;

        if (is_uploaded_file($this->tmpPath)){

            move_uploaded_file($this->tmpPath,$filename);

        }

    }

    //建立上传文件夹

    private function touchDir(){

        if(!file_exists($this->filepath)){

            return mkdir($this->filepath);

        }

    }

    //开始接受上传

    public function start()

    {

        $this->moveFile();

        $this->fileMerge();

    }

}

//实例化并获取系统变量传参

$upload = new Upload($_FILES['file']['tmp_name'],$_POST['blockNum'],$_POST['blockNumSum'],$_POST['fileName']);

$upload->start();

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 6,653评论 1 10
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 6,261评论 0 2
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,769评论 0 38
  • 【0224 读书感悟】3078-Why小賢 书名:《干法》 作者:稻盛和夫 金句: 不是为了击败对手而拼命,而是为...
    Why小賢阅读 1,769评论 0 0
  • 本周已经是父母课堂的第四个学习主题了,转眼间,父母课堂已经开讲了一个月了,这一个月的收获还是很大的! 记得第一次讲...
    乐瞳妈咪阅读 3,514评论 0 1

友情链接更多精彩内容