<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input id="fileInput" type="file" />
<img id="img" src="" alt="" />
<img id="blobImg" src="" alt="" />
<img style="width: 90%;" id="yuanblobImg" src="" alt="" />
</body>
<script>
let fileId = document.getElementById("fileInput");
let img = document.getElementById("img");
fileId.onchange = function (e) {
console.log(e);
let file = e.target.files[0];
fileToBase64(file, 0.2);
};
const fileToBase64 = (file, quality) => {
console.log(file.size / 1024 / 1024);
console.log("将file文件通过FileReader转化为base64格式");
let fileReader = new FileReader();
let type = file.type;
fileReader.readAsDataURL(file);
fileReader.onload = function (e) {
console.log("原始二进制字符串:", this.result.toString());
compress(fileReader.result, quality, type);
};
};
const MAX_WIDTH = 800;
const compress = (base64, quality, mimeType) => {
console.log(
"处理base64数据,通过canvas(toDataURL)进行压缩绘制,然后输出压缩后的base64图片数据"
);
document.getElementById("yuanblobImg").src = base64;
let cvs = document.createElement("canvas");
let img = document.createElement("img");
img.crossOrigin = "anonymous";
return new Promise((resolve, reject) => {
img.src = base64;
let offetX = 0;
img.onload = () => {
if (img.width > MAX_WIDTH) {
cvs.width = MAX_WIDTH;
cvs.height = (img.height * MAX_WIDTH) / img.width;
offetX = (img.width - MAX_WIDTH) / 2;
} else {
cvs.width = img.width;
cvs.height = img.height;
}
let ctx = cvs
.getContext("2d")
.drawImage(img, 0, 0, cvs.width, cvs.height);
let imageData = cvs.toDataURL(mimeType, quality);
console.log("canvas图片压缩", imageData);
let blobData = converrVase64UrlToBlob(imageData, mimeType);
console.log("我想转成blob格式看看", blobData);
console.log(blobData.size);
console.log(2.8 * 1024 * 1024);
resolve(imageData);
};
});
};
const converrVase64UrlToBlob = (base64, mimeType) => {
console.log("base64数据转成blob文件流");
let bytes = window.atob(base64.split(",")[1]);
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
let _blob = new Blob([ia], { type: mimeType });
toImg(_blob);
return _blob;
};
const toImg = function (blobObj) {
console.log("尝试操作成功转化的blob文件");
let imgSrc = window.URL.createObjectURL(blobObj);
document.getElementById("blobImg").src = imgSrc;
};
</script>
</html>
const fileToDataURL = file => new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = e => resolve(e.target.result);
reader.readAsDataURL(file);
});
const dataURLToImage = dataURL => new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(img);
img.src = dataURL;
});
const canvastoFile = (canvas, type, quality) => new Promise(resolve => canvas.toBlob(blob => resolve(blob), type, quality));
const compress = (originfile, maxSize) => new Promise(async (resolve, reject) => {
const originSize = originfile.size / 1024;
console.log('图片指定最大尺寸为', maxSize, '原始尺寸为:', originSize);
const base64 = await fileToDataURL(originfile);
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
if (originSize < maxSize) {
resolve({ compressBase64: base64, compressFile: originfile });
console.log(`图片小于指定大小:${maxSize}KB,不用压缩`);
return;
}
const img = await dataURLToImage(base64);
const scale = 1;
const originWidth = img.width;
const originHeight = img.height;
const targetWidth = originWidth * scale;
const targetHeight = originHeight * scale;
canvas.width = targetWidth;
canvas.height = targetHeight;
context.clearRect(0, 0, targetWidth, targetHeight);
context.drawImage(img, 0, 0, targetWidth, targetHeight);
const maxQualitySize = { quality: 100, size: Number.MAX_SAFE_INTEGER };
const minQualitySize = { quality: 0, size: 0 };
let quality = 100;
let count = 0;
let compressFinish = false;
let invalidDesc = '';
let compressBlob = null;
while (!compressFinish && count < 12) {
compressBlob = await canvastoFile(canvas, 'image/jpeg', quality / 100);
const compressSize = compressBlob.size / 1024;
count++;
if (compressSize === maxSize) {
console.log(`压缩完成,总共压缩了${count}次`);
compressFinish = true;
return;
}
if (compressSize > maxSize) {
maxQualitySize.quality = quality;
maxQualitySize.size = compressSize;
}
if (compressSize < maxSize) {
minQualitySize.quality = quality;
minQualitySize.size = compressSize;
}
console.log(`第${count}次压缩,压缩后大小${compressSize},quality参数:${quality}`);
quality = Math.ceil((maxQualitySize.quality + minQualitySize.quality) / 2);
if (maxQualitySize.quality - minQualitySize.quality < 2) {
if (!minQualitySize.size && quality) {
quality = minQualitySize.quality;
} else if (!minQualitySize.size && !quality) {
compressFinish = true;
invalidDesc = '压缩失败,无法压缩到指定大小';
console.log(`压缩完成,总共压缩了${count}次`);
} else if (minQualitySize.size > maxSize) {
compressFinish = true;
invalidDesc = '压缩失败,无法压缩到指定大小';
console.log(`压缩完成,总共压缩了${count}次`);
} else {
console.log(`压缩完成,总共压缩了${count}次`);
compressFinish = true;
quality = minQualitySize.quality;
}
}
}
if (invalidDesc) {
console.log(`压缩失败,无法压缩到指定大小:${maxSize}KB`);
reject({ msg: invalidDesc, compressBase64: base64, compressFile: originfile });
return;
}
compressBlob = await canvastoFile(canvas, 'image/jpeg', quality / 100);
const compressSize = compressBlob.size / 1024;
console.log(`最后一次压缩(即第${count + 1}次),quality为:${quality},大小:${compressSize}`);
const compressedBase64 = await fileToDataURL(compressBlob);
const compressedFile = new File([compressBlob], originfile.name, { type: 'image/jpeg' });
resolve({ compressFile: compressedFile, compressBase64: compressedBase64 });
});
export default compress;