HTML5实现图片压缩上传,主要用到FileReader, canvas, Blob,FormData这几个api
1,fileReader用来读取文件
2,利用canvas.toDataURL('"image/jpeg",quality)中的quality参数进行图片压缩
3,将图片base64格式转化为blob对象
4,利用formData上传
首先介绍下FileReader, canvas, Blob,FormData各自的使用场景,着重介绍下FileReader,Blob
Blob常见使用场景
① 大文件分割上传
② 图片跨域请求,处理跨域问题,参考 createjs ImageLoader.js
③ 隐藏视频源路径
具体参见https://www.leevii.com/2018/08/blob-object-in-javascript.html
FileReader
HTML5提供了FileReader
的api,FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。
FileReader对象有三个来源:
1,input选择文件
2,拖拽
生成的 DataTransfer
对象
3,HTMLCanvasElement
上执行mozGetAsFile()
方法后返回结果。(只支持fireForx,基本不使用)
FileReader的属性:
1,FileReader.error 表示读取文件时发生的错误
2,
FileReader.readyState
读取文件的状态
常量名 | 值 | 描述 |
EMPTY | 0 | 还没有加载任何数据. |
LOADING | 1 | 数据正在被加载. |
DONE | 2 | 已完成全部的读取请求. |
3,FileReader.result 读取完成后
FileReader的事件处理:
1,FileReader.onabort 读取操作被中断时触发
2,
FileReader.onerror 发生错误时触发
3,
FileReader.onload 文件读取操作完成时触发
4,
FileReader.onloadstart 文件读取操作开始时触发
5,FileReader.onloadend
在读取操作结束时(要么成功,要么失败)触发。
6,FileReader.onprogress
在读取Blob
时触发
FileReader的方法:
1,FileReader.abort()
中止读取操作。在返回时,readyState
属性为DONE
。
2,FileReader.readAsArrayBuffer()
开始读取指定的 Blob
中的内容, 一旦完成, result 属性中保存的将是被读取文件
的 ArrayBuffer
数据对象.
3,FileReader.readAsBinaryString()
开始读取指定的Blob
中的内容。一旦完成,result
属性中将包含所读取文件的
原始二进制数据。
4,FileReader.readAsDataURL()
开始读取指定的Blob
中的内容。一旦完成,result
属性中将包含一个data:
URL格式
的字符串以表示所读取文件的内容。
5,FileReader.readAsText()
开始读取指定的Blob
中的内容。一旦完成,result
属性中将包含一个字符串以表示所读取
的文件内容。
fileReader的具体使用实例:
<label for = "upload"> 上传文件 </label>
<input id = "upload" type = "file" onChange = {this.uploadFile}/><br/>
<img src = {this.state.imgurl} />
//读取文件为url
uploadFile = (e) => {
const file = e.target.files[0] || e.dataTransfer.files[0]
if(!file){return false}
const reader = new FileReader();
reader.readAsDataURL(file)
reader.onload = e => {
this.setState({imgurl:reader.result})
}
}
图片压缩:图片压缩主要用到canvas的drawImage
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
定义canvas
uglifyImg = () => {
//uglify ['ʌglɪˌfaɪ] v 混淆 压缩合并
const image = new Image(), //new Image()的功能等价于 document.createElement('img')
canvas = document.getElementById("canvas"),
ctx = canvas.getContext('2d');
image.src = this.state.imgurl;
image.onload = () => {
let w = image.naturalWidth,
h = image.naturalHeight;
console.log(w,h)
canvas.width = w;
canvas.height = h;
ctx.drawImage(image, 0, 0, w, h, 0, 0, w, h);
let data = canvas.toDataURL("image/jpeg",0.5);//dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
data = data.split(',')[1];
data = window.atob(data) //atob() 解析一个base-64的字符串 ;btoa() 方法用于创建一个 base-64 编码的字符串
this.fileUpload(data)
}
}
上传文件
fileUpload = (data) => {
let ia = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i); //charCodeAt() 方法可返回指定位置的字符的 Unicode 编码
};
let blob = new Blob([ia], {
type: "image/jpeg"
});
let fd = new FormData();
fd.append('myFile', blob);
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", opts.success, false);
xhr.addEventListener("error", opts.error, false);
xhr.open("POST", opts.url);
xhr.send(fd);
}