base64图片压缩上传(前后端demo)
一、前端代码
<input type="file" id="imgfile" method="post" enctype="multipart/form-data">
<button type="button" onclick="ToBase64();">
js代码
function ToBase64() {
var img = document.getElementById('imgfile')
var imgFile = new FileReader();
if(img.files[0] != null){//判断是否选择了图片
imgFile.readAsDataURL(img.files[0]);
}
var imgData ="";
imgFile.onload = async function () {
var imgData = this.result; //base64数据
console.log(imgData.length);
var str = await dealImage1(imgData, 500);//图片压缩
console.log(str.length);
console.log(str);
api.ajax({
//这里是自己请求后台的方法
});
}
}
前端图片压缩方法,可以直接使用https://blog.csdn.net/zx19930309/article/details/90375907
但是他用的是回调方式不能完全满足我的需求,所以在同事的帮助下做出了一点更改
function dealImage1(base64, w) {
return new Promise((res,ret) => {
var newImage = new Image();
var file = "";
var quality = 0.6; //压缩系数0-1之间
newImage.src = base64;
newImage.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
var imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = w * imgHeight / imgWidth;
} else {
canvas.height = w;
canvas.width = w * imgWidth / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
quality = 0.6;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
//如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定
while (base64.length / 1024 > 150) {
quality -= 0.01;
base64 = canvas.toDataURL("image/jpeg", quality);
}
//防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑
while (base64.length / 1024 < 50) {
quality += 0.001;
base64 = canvas.toDataURL("image/jpeg", quality);
}
file = base64;
console.log(base64.length);
console.log(file.length);
res(file)
}
})
}
二、后台java代码
controller根据自己项目框架直接获取前端传递的字符串便可
public String fileUpload(String file) {
//验证
if(file == null || file.isEmpty()) {
throw new MestarException("未找到文件!");
}
// 获取路径
String fileUrl = mbfDocService.getFilePath();//这个按自己项目实际需求获取路径
// 替换
file = file.replaceAll(" ", "+");
int index = file.indexOf(",");
file = file.substring(index + 1);
System.out.println(file);
String name = TimeUtils.dateToString(new Date(), TimeUtils.DF_SIMPLE_YMDHMS);
String fileName = name + "." + "jpg";
File file1 = new File(fileUrl + fileName);
try {
// 解码,然后将字节转换为文件
byte[] bytes = Base64.decodeBase64(file);// 将字符串转换为byte数组
// byte[] bytes = Base64.getDecoder().decode(file);
// 判断文件夹是否存在
File targetFile = new File(fileUrl);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
boolean copyByte2File = this.copyByte2File(bytes, file1);
if (!copyByte2File) {
throw new MestarException("上传失败!");
} else {
return fileName;
}
} catch (Exception ioe) {
ioe.printStackTrace();
throw new MestarException("上传失败!," + ioe.getMessage());
}
}
前端传递给后台base64字符串中会出现缺失被替换的情况
所有我把被替换的+号全部复原,并且将data:image/jpg;base64,
开头截取掉
file = file.replaceAll(" ", "+");
int index = file.indexOf(",");
file = file.substring(index + 1);
二进制流上传图片
public boolean copyByte2File(byte[] bytes, File file) {
FileOutputStream out = null;
try {
// 转化为输入流
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
// 写出文件
byte[] buffer = new byte[1024];
out = new FileOutputStream(file);
// 写文件
int len = 0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len); // 文件写操作
}
return true;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
三、java后台压缩
后台压缩使用Thumbnails进行压缩
引入依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
在上传时压缩,但是后台压缩会有一个弊端,虽然简单方便但是对于程序而言执行时间会比前端压缩更长
只用一行代码便可以实现
Thumbnails.of(in).scale(0.1f).toOutputStream(out);