前两天公司业务上有需求需要将较大的图片压缩后再传到远程服务器,网上找了不少方法都不太好用,今天有空索性自己写了一个方法,并把它放到了自己的github上,有兴趣的同学可以戳这里
一、需求是什么?
首先想一想我们有哪些需求?大多时候我们需要将一个File对象压缩之后再变为File对象传入到远程图片服务器;有时候我们也需要将一个base64字符串压缩之后再变为base64字符串传入到远程数据库;有时候后它还有可能是一块canvas画布,或者是一个Image对象,或者直接就是一个图片的url地址,我们需要将它们压缩上传到远程;面对这么多的需求,王二索性画了一张图:
[图片上传失败...(image-d58aa3-1510824060109)]
二、解决办法
如上图所示,王二一共写了七个方法,基本覆盖了JS中大部分文件类型的转换与压缩,其中:
1、urltoImage(url,fn)
会通过一个url加载所需要的图片对象,其中url
参数传入图片的url
,fn
为回调方法,包含一个Image对象的参数,代码如下:
function urltoImage (url,fn){
var img = new Image();
img.src = url;
img.onload = function(){
fn(img);
}
};
2、imagetoCanvas(image)
会将一个Image
对象转变为一个Canvas
类型对象,其中image
参数传入一个Image对象,代码如下:
function imagetoCanvas(image){
var cvs = document.createElement("canvas");
var ctx = cvs.getContext('2d');
cvs.width = image.width;
cvs.height = image.height;
ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
return cvs ;
};
3、canvasResizetoFile(canvas,quality,fn)
会将一个Canvas
对象压缩转变为一个Blob
类型对象;其中canvas
参数传入一个Canvas
对象;quality
参数传入一个0-1的number
类型,表示图片压缩质量;fn
为回调方法,包含一个Blob
对象的参数;代码如下:
function canvasResizetoFile(canvas,quality,fn){
canvas.toBlob(function(blob) {
fn(blob);
},'image/jpeg',quality);
};
这里的
Blob
对象表示不可变的类似文件对象的原始数据。Blob
表示不一定是JavaScript
原生形式的数据。File
接口基于Blob
,继承了Blob
的功能并将其扩展使其支持用户系统上的文件。我们可以把它当做File类型对待,其他更具体的用法可以参考MDN文档
4、canvasResizetoDataURL(canvas,quality)
会将一个Canvas
对象压缩转变为一个dataURL
字符串,其中canvas
参数传入一个Canvas
对象;quality
参数传入一个0-1的number
类型,表示图片压缩质量;代码如下:
methods.canvasResizetoDataURL = function(canvas,quality){
return canvas.toDataURL('image/jpeg',quality);
};
其中的
toDataURL
API可以参考MDN文档
5、filetoDataURL(file,fn)
会将 File
(Blob
)类型文件转变为dataURL
字符串,其中 file
参数传入一个File
(Blob
)类型文件;fn
为回调方法,包含一个dataURL
字符串的参数;代码如下:
function filetoDataURL(file,fn){
var reader = new FileReader();
reader.onloadend = function(e){
fn(e.target.result);
};
reader.readAsDataURL(file);
};
6、dataURLtoImage(dataurl,fn)
会将一串dataURL
字符串转变为Image
类型文件,其中dataurl
参数传入一个dataURL
字符串,fn
为回调方法,包含一个Image
类型文件的参数,代码如下:
function dataURLtoImage(dataurl,fn){
var img = new Image();
img.onload = function() {
fn(img);
};
img.src = dataurl;
};
7、dataURLtoFile(dataurl)
会将一串dataURL
字符串转变为Blob
类型对象,其中dataurl
参数传入一个dataURL
字符串,代码如下:
function dataURLtoFile(dataurl) {
var arr = dataurl.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});
};
三、进一步封装
对于常用的将一个File
对象压缩之后再变为File
对象,我们可以将上面的方法再封装一下,参考如下代码:
function fileResizetoFile(file,quality,fn){
filetoDataURL (file,function(dataurl){
dataURLtoImage(dataurl,function(image){
canvasResizetoFile(imagetoCanvas(image),quality,fn);
})
})
}
其中,file
参数传入一个File
(Blob
)类型文件;quality
参数传入一个0-1
的number
类型,表示图片压缩质量;fn
为回调方法,包含一个Blob
类型文件的参数。
它使用起来就像下面这样:
var file = document.getElementById('demo').files[0];
fileResizetoFile(file,0.6,function(res){
console.log(res);
//拿到res,做出你要上传的操作;
})
这样的话,图片压缩上传就能轻松地搞定了,以上的8个方法我已经封装好放到github上了,喜欢的话可以使劲的star哈。
参考文档:
MDN
原文地址:
王玉略的个人网站