图片的上传通常状况下不须要上传大致积的图片,由于若是是用户头像或者是一些要求清晰度不是过高的场景上传大致积图片会很消耗资源,一个是上传耗时比较长,同时也增长了存储的开销,当展现的时候也会消耗下载的带宽,影响加载效率。要求用户上传的图片以前压缩图片很影响用户体验,因此就增长了在前端进行图片压缩的需求。javascript
前端图片压缩的主要思路就是将图片绘制到canvas中,而后经过canvas的toDataURL方法来控制图片的质量,对图片进行压缩,另外一方面是对图片进行宽高等比缩小来达到图片压缩的效果,下面来看一下代码示例:前端
resizeMe(img,type, max_width, max_height) {
var canvas = document.createElement('canvas');
var width = img.width;
var height = img.height;
max_width = !isNaN(max_width)?max_width:0;
max_height = !isNaN(max_height)?max_height:0;
// 在这里图片是等比例缩放的,调用方法时填入图片容许的最大宽度或者是最大的高度
//若是最大宽度为0 则按照最大高度固定,宽度自适应的方式来实现
//若是是最大高度为0,则按照最大的宽度来实现
if(max_width==0){
if (height > max_height) {
width = Math.round(width *= max_height / height);
height = max_height;
}
}
if(max_height==0){
if (width > max_width) {
height = Math.round(height *= max_width / width);
width = max_width;
}
}
canvas.width =width;
canvas.height = height;
var ctx = canvas.getContext("2d");
canvas.width =width;
canvas.height = height;
ctx.drawImage(img,0,0, width, height);
type = type === 'jpg'?"jpeg":type;
return canvas.toDataURL("image/"+type, 0.7);//这里的0.7值的是图片的质量
}
复制代码
在上面的代码中,咱们传入的参数主要有image对象,图片类型,图片的最大宽度和最大高度。调用方法时填入图片容许的最大宽度或者是最大的高度,进行等比绘制到canvas中,而后经过toDataURL来转换成base64格式返回,此时的图片就是压缩事后的图片。java
上面的示例说了图片压缩的过程,其中有一个参数是image对象,那么这个image对象是如何来的呢。node
selectFileImage(el){
var reader = new FileReader();
var file = el.target.files[0]
var fileName = file.name;
var fileType = file.name.split(".")[1];
reader.readAsArrayBuffer(file);
reader.onload = (ev) => {
var blob = new Blob([ev.target['result']]);
window['URL'] = window['URL'] || window['webkitURL'];
var blobURL = window['URL'].createObjectURL(blob);
var image = new Image();
image.src = blobURL;
image.onload = (e) => {
var thumb = this.resizeMe(image,fileType, 400, 0);//得到的路径是将图片转换成了base64
axios.post("http://127.0.0.1:3003/useasync/upload",{file:thumb,fileName:fileName}).then(res => {
if (res.data.code == 200) {
console.log(res)
} else {
console.log(res)
}
});
}
}
}
复制代码
在这里面我使用了一个FileReader对象,FileReader 对象容许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。ios
当触发input的onChange事件后,能够读取到input中的file文件,因而将此文件读取到缓存当中,当读取完成后,result属性中保存的将是被读取文件的ArrayBuffer数据对象。这里咱们能够看一下读取完成后的这个ev究竟是个什么东西 咱们能够看到这里面loaded和total都表示的是文件的总大小,重要的实际上是target和currentTarget,这两个属性实际上是同样的,里面包含了读取的fileReader对象,里面的result就是缓存中的数据了,咱们经过new 一个Blob对象,将其转换为Blob对象,而后就能够经过url方法来将其转换为能够放到img src中的连接形式了。此时建立image对象,并对其src进行赋值,当image加载完成后,就开始调用压缩方法,传入的image对象就是咱们刚才生成的image对象。web
当压缩完成后返回的数据就是base64的数据了,咱们就能够经过ajax异步来进行上传,在此我采用的是axios进行异步上传,将内容及文件名做为参数传递给后台。ajax
在这我才用的示例为nodejs搭建后台来接收图片,这里咱们须要一个bodyParser模块json
app.use(bodyParser.json({ limit:'5mb'}));//限制容许提交的大小
复制代码
将大小限制为5M之内,也就是说经过base64上传的图片大小必定要小于5M才能成功,这个参数咱们能够随意更改,按业务需求而定。canvas
router.post("/upload",function(req,res){
var imgData = req.body.file;
var fileName = req.body.fileName;
var base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
//var size = Buffer.byteLength(base64Data,'base64');
//var dataBuffer = Buffer.alloc(size,base64Data, 'base64');
var dataBuffer = Buffer.from(base64Data, 'base64');
fs.writeFile(process.cwd()+"/upload/"+fileName, dataBuffer, function(err) {
if(err){
res.json({success:false,errormsg:err});
}else{
res.send({success:true,msg:"保存成功!"});
}
});
})
复制代码
接口中咱们经过Buffer来将base64转换为buffer,进而保存到服务器本地中,本示例采用的就是将图片保存到服务器本地。如此经过将base64编码图片保存为图片就作完了。axios
因为压缩采用的是canvas,获取文件等是经过FileReader 对象及Bolb对象,故此方法目前的兼容性最低为IE10,还请酌情使用。
文章发表自:前端图片压缩及上传