基于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>
备注:压缩性能与客户端性能成正相关。不宜过大。