上传图片以及使用canvas压缩图片
用input[‘file’]上传文件并设置类型为图片
<input type="file" id="personFile" accept='image/*' @change="upload">
在上传头像的时候,首先要把type设置为file,表示这个input是用来实现上传图片功能的,再把accept设置为’image/*’,这样就只能上传图片
<input type="file" id="personFile" accept='image/*' @change="upload">
因为他的样式不好改变,因此我们可以用一个div盒子把input框包住,然后把input的opacity设置为0,再给div盒子设置宽高和背景以及初始图片
<div id="personImg">
<input type="file" id="personFile" accept='image/*' @change="upload">
</div>
#person #personFile{
width: 100%;
height: 100%;
margin:0;
border-radius: 50%;
padding: 0;
cursor: pointer;
opacity:0;
}
#personImg{
margin-left:20px;
width: 82px;
height: 82px;
border-radius: 50%;
background: url('../../../../../static/2/add.png') no-repeat center;
background-size: 'auto 100%';
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
}
利用FileReader的readAsDataURL读取图片将其转为base64
在学习这个功能之前,我们首先来了解一下Blob对象和FileReader对象
Blob 对象
表示一个不可变、原始数据的类文件对象。Blob
表示的不一定是JavaScript
原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。
FileReader.onload
处理load事件。该事件在读取操作完成时触发。FileReader.result
只读
文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。
读取方法
FileReader.abort()
中止读取操作。在返回时,readyState属性为DONE。FileReader.readAsArrayBuffer()
开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.FileReader.readAsBinaryString()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。FileReader.readAsDataURL()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。FileReader.readAsText()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。
从Blob中读取内容的唯一方法是使用 FileReader。以下代码将 Blob 的内容作为url读取:
var oImg = new Image();
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = function (e) {
base64Code = this.result;
oImg.src = base64Code;
oPic.style = "background:"+ 'url(\''+base64Code+'\') no-repeat'+ ';background-position:center;background-size:auto 100%;background-color: white;'
}
在上述代码中,我们把上传图片绑定到input的change事件上,通过FileReader
对象来异步读取存储在用户计算机上的文件
onload
事件会在文件读取成功之后触发,FileReader
对象的result
属性存储着data: URL格式的字符串,我们把读取到的图片url赋值给input外包着的div结点以及新创建的img对象,给用户做出图片已经上传的假象
使用canvas压缩图片
我们首先了解一下canvas
- canvas 元素不被一些老的浏览器所支持,但是所有的主流浏览器的新近版本都支持。Canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。但是,可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。
- canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。它元素有一个叫做 getContext() 的方法,这个方法是用来获得渲染上下文和它的绘画功能。getContext()只有一个参数,即上下文的格式。
在获得了源图对象的情况下,可以使用 drawImage 方法将它渲染到 canvas 里。
- drawImage(image, x, y)
其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。 - drawImage(image, x, y, width, height)
这个方法多了2个参数:width 和 height,这两个参数用来控制缩放的图片大小 - drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
canvas.toBlob(callback, mimeType, qualityArgument) 创造Blob对象,用以展示canvas上的图片;这个图片文件可以被缓存或保存到本地,由用户代理端自行决定。
callback
回调函数,可获得一个单独的Blob对象参数。
type 可选
DOMString类型,指定图片格式,默认格式为image/png。
encoderOptions 可选
Number类型,值在0与1之间,当请求图片格式为image/jpeg或者image/webp时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内,则使用默认值,其余参数将被忽略。
接着上面来,之前我们已经获得了图片的base64,所以我们可以新生成一个Image对象,在监听该Image的load事件时,利用的canvas可以再获取源图对象的情况下,使用drawImage(image,x,y,width,height)的方法对图片进行压缩,然后利用canvas.toBlob将画好的canvas转为blob文件。
oImg.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
//获取图片的原始宽高
var originW = oImg.width;
var originH = oImg.height;
//设置图片压缩后的最大宽高
var maxW = 120, maxH = 120;
var targW = originW, targH = originH;
if(originW > maxW || originH > maxH) {
if(originH/originW > maxH/maxW) {
targH = maxH;
targW = Math.round(maxH * (originW / originH));
}else {
targW = maxW;
targH = Math.round(maxW * (originH / originW));
}
}
//对图片进行缩放canvas.toblob
canvas.width = targW;
canvas.height = targH;
//清除画布,在画之前清是因为会存在多次绘制的情况
context.clearRect(0,0,targW,targH);
//图片压缩
context.drawImage(oImg,0,0,targW,targH);
利用formdate上传文件
我们可以自己创建一个FormDate对象,然后调用它的append
方法来添加字段吗,像这样
var formData = new FormData();
formData.append("userfile", fileInputElement.files[0]);
使用append()方法时,可以通过第三个可选参数设置发送请求的头 Content-Disposition 指定文件名。如果不指定文件名(或者不支持该参数时),将使用名字“blob”。
- 一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File 接口基于Blob,继承 blob功能并将其扩展为支持用户系统上的文件。你可以通过 Blob() 构造函数创建一个Blob对象。
var newUrl = canvas.toDataURL('image/jpeg', 0.5);
//canvas转为blob并上传
canvas.toBlob(function (blob) {
var formData = new FormData();
formData.append("file",blob);
_this.$axios.post('weekly_war/user/photo.do', formData, {emulateJSON : true, withCredentials : true}).then(function(res) {
if(res.data.success) {
showPopRight(res.data.msg,_this);
window.localStorage.setItem('pic',base64Code);
}else {
showPopError(res.data.msg,_this);
}
})
},files.type || 'image/png');
}
FormData 对象的字段类型可以是 Blob, File, 或者 string: 如果它的字段类型不是Blob也不是File,则会被转换成字符串类。
注意,axios的配置里不要设置
{
headers: {
‘Content-Type’: ‘multipart/form-data’
}
}
正常以 multipart/form-data 编码方式提交请求体,生成的content-type 应该是这样的
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5NqxviCXpyAjOEV6
boundary 是浏览器自动生成的分割符, 如果自己设置了Content-Type,boundary 就会被覆盖掉,导致发送的FormData数据,参数为空