js大文件分片上传

<div class="btn uploadBtn right">
		                        <form enctype="multipart/form-data">
		                            <span>上传文件</span>
		                            <input class="file J_file" multiple="multiple" name="skin" type="file">
		                        </form>
		                    </div>
/**
 * @Author   SuZhe
 * @DateTime 2019-06-04
 * @desc     文件大小格式化单位
 * @param    {[Number]}   size        [文件大小]
 * @param    {[Number]}   pointLength [精确度]
 * @param    {[Array]}    units       [单位列表]
 * @return   {[String]}               [格式化单位]
 */
function formatFileSize(size, pointLength, units) {
  var unit;
  units = units || [ 'B', 'K', 'M', 'G' ];
  while ( (unit = units.shift()) && size > 1024 ) {
      size = size / 1024;
  }
  return (unit === 'B' ? size : size.toFixed( pointLength === undefined ? 2 : pointLength)) + unit;
}

/**
 * @Author   SuZhe
 * @DateTime 2019-06-03
 * @desc     多文件分割上传
 * @param    {[Object]}   op [配置参数]
 */
function UploadFile(op){
	this.cont = document.getElementsByClassName(op.ele);
	this.upSrc = op.src;
	this.stopUpFun = op.stopUp;
	this.url = op.url;
	this.init();
}

UploadFile.prototype = {
	init: function(){
		var _this = this;
		this.cutSize = 6 * 1024 * 1024;
		//up btn event
		$(this.cont).on("change", function(e){
			_this.upload(e,this);
		});
		//del
		$(document).on('click','.j_default .j_colse',function(){
			_this.stopUp(this);
		});
	},
	upload: function(e,context){
		var src, url = window.URL || window.webkitURL || window.mozURL, files = e.target.files,
	        $that    = $(context);

	    this.index = 0;
	    this.allFiles = [];
	    this.proHtml = '';

	    for (var i = 0, len = files.length; i < len; ++i) {
            this.allFiles.push(files[i]);
            var file = files[i],
            	name = file.name,
            	size = formatFileSize(file.size);
            //获取后缀名
            var extName = name.substring(name.lastIndexOf(".")).toLowerCase().replace(".","");
            this.proHtml += '<li class="clearx j_up_pro j_default"><em class="upFileProgressCont_em left file_'+extName+'"></em>\
								<div class="left cont">\
									<p class="name defaultname"><span class="left">'+name+'</span><span class="right j_show_size">等待上传...</span><span class="right j_show_upsize"></span></p>\
									<p class="name errorname"><span class="left">'+name+'</span><span class="right j_uperr"></span></p>\
									<p class="name successname"><span class="left">'+name+'</span><span class="left left1">'+size+'</span><span class="right">上传完成</span></p>\
									<div class="pro"><b style="width:0%;"></b></div>\
								</div>\
								<i class="j_colse right"></i>\
							</li>';
        }
		this.showProgress();
		this.sendData();
	    //重置数据
	    $that.val('');
	    
	},
	showProgress: function(){
		G.confirm({
			"text":'<div>\
						<p class="tit">上传文件</p>\
						<p class="tipText"><i class="tipIcon"></i>离开此页面会导致上传失败!</p>\
						<ul>'+this.proHtml+'</ul>\
					</div>',
			"pclass": "upFileProgressCont",
			"css":{width:646},
			"bclass": "none"
		});
	},
	sendData: function(){
		var _this = this,
			index = this.index,
			currentFile = this.allFiles[index];
		if(!this.totalSize){
			//存储当前文件总大小 防止超时重复读取数据
			this.totalSize = formatFileSize(currentFile.size);
			//dom节点缓存  当前上传展示DOM、总文件展示DOM、进度条DOM
			this.$uppar  = $('.j_up_pro').eq(index);
			this.$upsize = this.$uppar.find('.j_show_upsize');
			this.$size   = this.$uppar.find('.j_show_size');
			this.$pro    = this.$uppar.find('b');
			//总文件大小
			this.$size.html(this.totalSize);
			//切片个数
            this.shardCount = Math.ceil(currentFile.size / this.cutSize);
            //当前切片标识
            this.currentFileCutInde = 1;
            //是否需要分片
            this.isShard = this.shardCount === 1 ? false : true;
            this.currentFileArr = [];
            //分片数据优化
            if(this.isShard){
            	for(var i = 0, len = this.shardCount; i < len; i++){
            		var start = i * this.cutSize;
            		//最后一片文件小于800kb数据前移
            		var lastSize = currentFile.size - (i+1)*this.cutSize;
            		if(lastSize <= 800*1024 && lastSize>0){
            			var	end = currentFile.size;
            			i++;
            			this.shardCount--;
            		}else{
            			var	end = Math.min(currentFile.size, start + this.cutSize);	
            		}
            		this.currentFileArr.push(currentFile.slice(start, end));
            	}
            }else{
            	this.currentFileArr.push(currentFile);
            }
            //进度存储
            this.loaded = 0;
            this.prevLoaded = 0;
		}

		//formdata
		this.formData = new FormData();
		//更新文件片段
		this.formData.append('file', this.currentFileArr[this.currentFileCutInde-1]);
		this.formData.append('name', currentFile.name);
		this.formData.append('size', currentFile.size);

		//发起请求
		this.upHttp = $.ajax({
	         url: _this.url+'&isShard='+_this.isShard+'&current='+_this.currentFileCutInde+'&totalShard='+this.shardCount,
	         type: "POST",
	         cache: false,
	         data: _this.formData,
	         processData: false,
	         contentType:false,
	         xhr: function() {
	            var xhr = $.ajaxSettings.xhr();
	            if (xhr.upload) {
	                xhr.upload.addEventListener('progress', function(e) {
	                	_this.prevLoaded = e.loaded + _this.loaded;
                    	var count = Math.floor(_this.prevLoaded/currentFile.size*100)+'%',
                    		proSize = formatFileSize(_this.prevLoaded)+'/';
	                    _this.$upsize.html(proSize);
	                    _this.$pro.width(count);
	                }, false);
	            }
	            return xhr;
	         },
	         success: function (result) {
	         	var data = JSON.parse(result);
         		if(data.code === 10000){
         			//记录切片上传成功后的fid
         			_this.delFid = data.data.fid;
					//所有切片上传完成
	            	if(_this.shardCount === _this.currentFileCutInde){
	            		_this.$uppar.addClass('finish').removeClass('j_default');
	            		_this.next();
	            	}else{
	            		//进度存储
	            		_this.loaded = _this.prevLoaded;
	            		//切片后移
	            		_this.currentFileCutInde++;
	            	}
	            }else{
	            	_this.$uppar.addClass('error').removeClass('j_default').find('.j_uperr').html(data.desc);
	            	_this.next();
	            }

	            //上传完毕
	            _this.finish();
	         },
	         complete: function(XMLHttpRequest, status){
	         	if(status=='timeout'){
	         		_this.stopUp();
	         	}
	         }
	    });
	},
	stopUp: function(ele){
		var $par = ele ? $(ele).parents('li') : false;
		if($par && $par.find('.j_show_upsize').html() == ''){
			var index = $par.index();
			$par.remove();
			//删除待上传的文件
			this.allFiles.splice(index,1);
		}else{
			//暂停正在上传的文件
			this.upHttp.abort();
			//删除已经上传但未上传完毕的文件
			if(this.delFid){
				if(this.stopUpFun && typeof this.stopUpFun === 'function'){
					this.stopUpFun(this.delFid);
				}
			}
			//标识后移
			$par.addClass('cancelUp').removeClass('j_default').find('.j_uperr').html('已取消上传');
        	this.next();
        	//上传完毕
            this.finish();
		}
	},
	next: function(){
		//文件后移
		this.index++;
		//重置标识
    	this.reset();
	},
	finish: function(){
		//所有文件执行完毕
        if(this.index > this.allFiles.length-1){
        	var len = $('.upFileProgressCont .error').length,
        		errortip = '';
        	if(len > 0){
				errortip = len+'个文件上传失败,请重新上传!'
        	}
        	$('.upFileProgressCont').append('<div class="showresult clearx"><p class="left">上传完成!</p><p class="left errtip">'+errortip+'</p><a href="" class="btn right">确定</a></div>');
        	this.reset();
        	return false;
        }
        //再次请求下方文件
		this.sendData();
	},
	reset: function(){
		this.totalSize = null;
		this.$uppar = null;
		this.$upsize = null;
		this.$size = null;
		this.$pro = null;
		this.shardCount = null;
		this.currentFileCutInde = null;
		this.loaded = null;
		this.prevLoaded = null;
		this.upHttp = null;
		this.delFid = null;
		this.currentFileArr = null;
	}
}

var upFiles = new UploadFile({
    		ele: 'J_file',
            url:'uploadfile.php?packetid='+pid+'&dirid='+dirid,
            stopUp: function(fid){
                $.get('xxx.php?fid='+fid)
            }
    	})
.upFileProgressCont .c{padding: 0;}
.upFileProgressCont .tit{font-size: 14px;line-height: 40px;border-bottom: 1px solid #e5e5e5;}
.upFileProgressCont i{display: inline-block;width: 16px;height: 16px;background: url(../i/fileIcos/upFile.png);vertical-align: middle;}
.upFileProgressCont .tipIcon{background-position-y: -42px;}
.upFileProgressCont .tipText{text-align: left;color: #fe6749;line-height: 28px;background: #fffceb;}
.upFileProgressCont .tipText .tipIcon{margin: 0 5px 0 16px;}
.upFileProgressCont ul{height: 500px;overflow-y: auto;}
.upFileProgressCont li{padding: 15px 0;border-bottom: 1px solid #dddddd;}
.upFileProgressCont li .errorname,.upFileProgressCont li .successname,.upFileProgressCont li.error .name,.upFileProgressCont li.finish .name,.upFileProgressCont li.error .pro,.upFileProgressCont li.finish .pro{display: none;}
.upFileProgressCont li.error .errorname,.upFileProgressCont li.finish .successname{display: block;}
.upFileProgressCont li.error .name,.upFileProgressCont li.finish .name{padding-top: 5px;}
.upFileProgressCont li.error .name .right{color: #ff3333;}
.upFileProgressCont li.error i{background-position-y: -42px;}
.upFileProgressCont li.finish .left1{margin-left: 20px;color: #888888;}
.upFileProgressCont li.finish .name .right{color: #888888;}
.upFileProgressCont li.finish i{background-position-y: -64px;}
.upFileProgressCont li i{margin: 10px 15px 0 0;}
.upFileProgressCont .cont{width: 500px;}
.upFileProgressCont .name{height: 18px;padding-bottom: 5px;}
.upFileProgressCont .name .right{color: #888888;}
.upFileProgressCont .pro{width: 500px;height: 6px;background: #eaeaea;}
.upFileProgressCont .pro b{display: block;height: 6px;background: #5bc169;}
.upFileProgressCont .showresult{height: 52px;position: absolute;left: 1px;bottom: 0;border-top: 1px solid #e5e5e5;background: #fff;z-index: 999;width:100%;line-height: 52px;box-sizing: border-box;padding: 0 20px;}
.upFileProgressCont .showresult .errtip{color: #666;margin-left: 10px;}
.upFileProgressCont .showresult .btn{margin-top: 10px;}
.upFileProgressCont_em{display: block;width: 30px;height: 32px;margin: 0 20px;background: url(../i/fileIcos/file-otherIco.png);}
.doc,.docx,.dotx,.dot,.docm,.dotm,.xps,.mht,.mhtml,.rtf,.xml,.odt{background: url(../i/fileIcos/wordIco.png);}
.xls,.xlsx,.xlsb,.xlsm,.xlst{background: url(../i/fileIcos/elxIco.png);}
.ppt,.pptx{background: url(../i/fileIcos/pptIco.png);}
.pdf{background: url(../i/fileIcos/pdfIco.png);}
.move,.mp4,.avi,.wmv,.f4v,.rm,.rmvb,.wmv,.mid,.mpeg,.mpg,.dat{background: url(../i/fileIcos/videoIco.png);}
.jpg,.jpeg,.png,.gif,.bmp,.jpeg2000{background: url(../i/fileIcos/imageIco.png);}
.rar,.zip{background: url(../i/fileIcos/zipIco.png);}
.upFileProgressCont .txt{background: url(../i/fileIcos/textIco.png);}
.psd{background: url(../i/fileIcos/psdIco.png);}
.psd{background: url(../i/fileIcos/psdIco.png);}
.cda,.mp3,.wav,.ape,.flac,.m4a,.ogg,.amr,.wma,.aac,.aiff,.caf{background: url(../i/fileIcos/audioIco.png);}
.ai{background: url(../i/fileIcos/aiIco.png);}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值