作者:mylvfamily | 2021-08-16 08:13
JS压缩上传图片
/**
* @Date: 2016/11/17 0017
* @Time: 10:14
* @Author: lxbin
*
* Created with JetBrains WebStorm.
*/
/**
* http://leonshi.com/2015/10/31/html5-canvas-image-compress-crop/
* http://jafeney.com/2016/08/11/20160811-image-upload/
*/
/**
* 读取文件
* @param file 文件对象
* @return {Promise}
*/
function readFileAsync(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = e => resolve(readFile.target.result)
reader.onerror = e => reject(new Error('Could not read file'))
reader.readAsDataURL(file)
})
}
/**
* 加载图片
* @param url 图片地址
* @return {Promise}
*/
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
const image = new Image()
image.onload = () => resolve(image)
image.onerror = () => reject(new Error('Could not load image at ' + url))
image.src = url
})
}
/**
* base64的图片dataUri转Blob
* @param dataURI
* @return {*}
*/
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;
// Old code
// var bb = new BlobBuilder();
// bb.append(ab);
// return bb.getBlob(mimeString);
}
/**
* 图片转Blob
* @param image 图片对象
* @param quality 图片质量(0到1之间)
* @param scale 缩放比例(0到1之间)
* @return {Promise}
*/
function imageToBlob(image, quality, scale) {
return new Promise((resolve, reject) => {
try {
let canvas = document.createElement('canvas')
canvas.width = image.naturalWidth * scale
canvas.height = image.naturalHeight * scale
while (canvas.width >= 3264 || canvas.height >= 2448) {//超过这个值base64无法生成,在IOS上
canvas.width = canvas.naturalWidth * scale
canvas.height = canvas.naturalHeight * scale
}
let ctx = canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height)
//方式一:低版本兼容性差些
//canvas.toBlob(function (blob) {
// console.group('[Leo]file compress to blob')
// console.log('文件类型 => ' + file.type)
// console.log('文件大小 => ' + (file.size / 1024 / 1024).toFixed(2) + 'M')
// console.log('blob质量 => ' + quality)
// console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M')
// console.groupEnd()
// resolve(blob)
//}, 'image/jpeg', quality)
//方式二:
var base64 = canvas.toDataURL('image/jpeg', quality);
var blob = dataURItoBlob(base64);
console.group('[Leo]file compress to blob')
console.log('文件类型 => ' + file.type)
console.log('文件大小 => ' + (file.size / 1024 / 1024).toFixed(2) + 'M')
console.log('blob质量 => ' + quality)
console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M')
console.groupEnd()
resolve(blob);
} catch (e) {
reject(new Error("Image could not convert to blob :" + e))
}
})
}
/**
* Ajax上传
* @param uri 上传的Action地址
* @param file 文件对象
* @return {Promise}
*/
function uploadFile(uri, file) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
if (xhr.upload) {
xhr.upload.addEventListener("progress", (e) => {// 处理上传进度
if (e.lengthComputable) {
let percent = (e.loaded / e.total * 100).toFixed(2) + '%'
console.log("上传中(" + percent + ")");
//TODO:反馈到DOM里显示
} else {
console.log('unable to compute');
}
}, false)
}
xhr.onreadystatechange = (e) => {// 文件上传成功或是失败
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.responseText)// 上传成功
} else {
reject(xhr.responseText)// 上传出错处理
}
}
}
xhr.open("POST", uri, true)// 开始上传
let form = new FormData()
form.append("filedata", file)
xhr.send(form)
})
}
/**
* 上传文件
* @param file 文件对象
* @param quality 图片质量(0到1之间)
* @param scale 缩放比例(0到1之间)
*/
export default async function fileUpload(file, quality, scale) {
try {
let fileUrl = await readFileAsync(file)
let image = await loadImageAsync(fileUrl)
let blob = await imageToBlob(image, quality, scale)
let upload = await uploadFile(blob)
return upload
} catch (e) {
console.log('file upload failed')
}
}