jquery 实现图片压缩上传

基于jQuery,通过使用canvas标签将文件压缩转换为base64字符串后,再通过Blob对象实现ajax文件上传.

/**
 * 制造一个自定义的文件压缩框 <br/>目前支持单文件上传
 * 
 * @param createCompressFileBox
 * @param searchid
 * @param data
 * @returns
 */
function createCompressFileBox(dom, data) {
    var fileOper = {
	/**
	 * 获得源文件
	 */
	getFile : function(){
	    return dom[0].files[0];
	},
	/**
	 * 设置需要上传的表单(除开文件框)
	 */
	getForm : function() {
	    var form = new FormData();
	    // 上传:如果在配置json里存在url,
	    if (!data.url) {
		var formObj = dom.parent('form');
		data.url=formObj.attr('action');
		if(!data.url){
		    console.error('没有action');
		    return false;
		}
	    }
		// 上传附件数据  存在 则说明该文件框独立上传。
	    if (data.data) {
		$.each(data.data, function(i, t) {
    		     form.append(i, t);
		});
	    }else {
		var formObj = dom.parent('form');
		var vals = formObj.children("input[name]");
		$.each(vals, function(i, t) {
		    if(t.name!='file'){
		       form.append(t.name, t.val());
		    }else{
		       if(dom[0]!=t)
		       form.append(t.name,t[0].files[0], t[0].files[0].name);
		    }
		});
	    }
	    return form;
	},
	/**
	 * 计算压缩比例
	 */
	calculatequality:function(file){
	    var compresssize = data.compresssize || 1024;
	    var quality =file.size/1024> compresssize ? 1 / (file.size/1024/compresssize) : 1;
	    return quality;
	},
	/**
	 * 开始图片压缩(异步)
	 */
	compress : function(file, success) {
	    fileOper.compressMethod.checkRun(data.beforeCompress,function(){
    		    // 将图片压缩到指定的压缩大小为止 默认1mb (单位kb)
		    var quality =fileOper.calculatequality(file);
		    if(quality<1){
			// 开始压缩
			fileOper.compressMethod.photoCompress(file, {
	                    quality: quality
	                }, function(base64Codes){
	                    fileOper.compressMethod.checkRun(data.afterCompress,function(){
				success(fileOper.compressMethod.convertBase64UrlToBlob(base64Codes));
			   });
	                });
		    }else{
			// 不需要压缩
			fileOper.compressMethod.checkRun(data.afterCompress,function(){
			    success(file);
			})
		    }
	    });
	},
	sourceloader:function(){
	    var formObj = dom.parent('form');
	    formObj.submit();
	},
	/**
	 * 文件上传(异步)
	 */
	loader : function(form) {
	    if(!form){
		console.error("缺失提交表单");
		return;
	    }
	    if (!data.beforeSubmit || false!=data.beforeSubmit(form)) {
		$.ajax({
		    url : data.url,
		    type : "POST",
		    data : form,
		    cache : false,
		    processData : false,
		    contentType : false,
		    success : function(json) {
			if (data.success) {
			    data.success(json);
			} else {
			    console.log("上传成功!");
			}
		    },
		    error : function(jqXHR, textStatus, errorThrow) {
			console.error("上传发生异常!");
			console.log(jqXHR);
			console.log(textStatus);
			console.log(errorThrow);
			if (data.error) {
			    data.error(jqXHR, textStatus, errorThrow);
			}
		    }
		});
	    }
	},
	/**
	 * 运行压缩并上传
	 */
	run : function(){
	    var file = fileOper.getFile();
	    fileOper.compress(file,function(newblob){
		var form = fileOper.getForm();
		if(form ==false)
		    return;
		form.append("file",newblob, file.name);
		console.log(newblob.size);
		console.log(newblob.size);
		fileOper.loader(form);
	    });
	}
    }
    
    fileOper.compressMethod = {
		/**
		 * 三个参数 file:一个是文件(类型是图片格式), w:一个是文件压缩的后宽度,宽度越小,字节越小
		 * objDiv:一个是容器或者回调函数 photoCompress()
		 */
		photoCompress : function(file, w, objDiv) {
		    var ready = new FileReader();
		    /**
		     * 开始读取指定的Blob对象或File对象中的内容.
		     * 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data:
		     * URL格式的字符串以表示所读取文件的内容.
		     */
		    ready.readAsDataURL(file);
		    ready.onload = function() {
			var re = this.result;
			fileOper.compressMethod.canvasDataURL(re, w, objDiv)
		    }
		},
		canvasDataURL : function(path, obj, callback) {
		    var img = new Image();
		    img.src = path;
		    img.onload = function() {
			var that = this;
			// 默认按比例压缩
			var w = that.width, h = that.height, scale = w / h;
			w = obj.width || w;
			h = obj.height || (w / scale);
			var quality = 0.7; // 默认图片质量为0.7
			// 生成canvas
			var canvas = document.createElement('canvas');
			var ctx = canvas.getContext('2d');
			// 创建属性节点
			var anw = document.createAttribute("width");
			anw.nodeValue = w;
			var anh = document.createAttribute("height");
			anh.nodeValue = h;
			canvas.setAttributeNode(anw);
			canvas.setAttributeNode(anh);
			ctx.drawImage(that, 0, 0, w, h);
			// 图像质量
			if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
			    quality = obj.quality;
			}
			// quality值越小,所绘制出的图像越模糊
			var base64 = canvas.toDataURL('image/jpeg', quality);
			// 回调函数返回base64的值
			callback(base64);
		    }
		},
		/**
		 * 将以base64的图片url数据转换为Blob
		 * 
		 * @param urlData
		 *                用url方式表示的base64图片数据
		 */
		convertBase64UrlToBlob : function(urlData) {
		    var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(
			    n);
		    while (n--) {
			u8arr[n] = bstr.charCodeAt(n);
		    }
		    return new Blob([ u8arr ], {
			type : mime
		    });
		},
		/**
		 * 判断是否存在需要前置运行的方法,存在则运行,并结果不为false的情况运行成功回调,如果不存在则直接执行回调
		 */
		checkRun:function(checkMethod,success){
    		    if(checkMethod){
			    if(false != checkMethod()){
				success();
	    		    }
    		    }else{
			    success();
		    }
		}
	    };
    dom.on('change',function(fil){
	if(data.change){
	    data.change(fil,fileOper.run());
	}else{
	    if(dom.val()&& dom.val()!==''){
		    // 存在选择文件后进行操作
		fileOper.run();
    	    }
	}
    });
    var test=function(){
	createCompressFileBox($('#id1'),{
	    url:'wecat/user/changeavatar?action=uploadimage',
	    beforeCompress:function(){
		},
		afterCompress:function(){
		},
		beforeSubmit:function(){
		},
		success:function(json) {
		},
		compresssize:5*1024// kb,
		,data:{
		    id:''
		},
	})
    }
}

test demo:


<form method="POST" id="case-img-input-form"
	enctype="multipart/form-data"
	action="${Domain}api/upload/loader" >
	<input id="case-img-input" style="display: none" name="file" type="file" accept="image/*">
</form>

<script>
	$(function(){
		createCompressFileBox($('#case-img-input'),{
			compresssize:800,
			beforeCompress:function(){
			    loadingToast({msg:'文件上传中...',timeout:-1});
			},
			success:function(json) {
			    fileloadersuccess(json);
			},change:function(file,success){
			    if($('#case-img-input').val()&&$('#case-img-input').val() !==''){
						success();
				}
			}
	    });
	})
	
	
	
</script>


//或
<input type="file" id="image-upload-input" accept=".jpg,.png,.jpeg" >


<script>
createCompressFileBox($('#image-upload-input'),{
		url:'${Domain}api/upload?action=uploadimage',
		beforeCompress:function(){
		},
		compresssize:800,
		success:function(json) {
		}
    });
</script>

备注:压缩性能与客户端性能成正相关。不宜过大。

转载于:https://my.oschina.net/yuyizyk/blog/1921606

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值