这个世界没有什么好畏惧的,反正我们只来一次。
前言
主要实现了两个功能:
编写代码
1.编写工具类
ImageUtil代码如下:
package com.example.demo.util;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@Slf4j
public class ImageUtil {
private static final float QUALITY = 0.09f;
private static final float LIMIT_SIZE = 500 * 1024;
public static byte[] compressPic(byte[] bytes) {
log.info("压缩前大小:{}{}", bytes.length / 1024, "kb");
if (bytes.length < LIMIT_SIZE) {
return bytes;
}
TimeInterval timer = DateUtil.timer();
BufferedImage bufferedImage = null;
float q = 0.9f;
byte[] result = null;
try {
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
bufferedImage = ImageIO.read(in);
while (q > QUALITY) {
result = compressPic(bufferedImage, q);
log.info("图片压缩后大小:{}{},质量参数:{}", result.length / 1024, "kb", q);
if (result.length > LIMIT_SIZE) {
q -= 0.1f;
} else {
q = 0f;
}
}
long interval = timer.interval();
log.info("图片压缩耗时:{}{}", interval, "ms");
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void pressText(String pressText, String targetImg) {
try {
TimeInterval timer = DateUtil.timer();
BufferedImage src = ImageIO.read(new File(targetImg));
int width = src.getWidth(null);
int height = src.getHeight(null);
int fontSize = width < height ? width / 300 * 15 : height / 300 * 15;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(src, 0, 0, width, height, null);
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.PLAIN, fontSize));
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.drawString(pressText, 20, fontSize * 12 / 10);
g.dispose();
File f = new File(targetImg);
ImageIO.write(image, targetImg.substring(targetImg.lastIndexOf(".") + 1), f);
long interval = timer.interval();
log.info("图片加水印耗时:{}{}", interval, "ms");
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] compressPic(BufferedImage image, float quality) throws IOException {
ByteArrayOutputStream outArray = new ByteArrayOutputStream();
ImageWriter imgWrier = ImageIO.getImageWritersByFormatName("jpg").next();
ImageWriteParam imgWriteParams = new javax.imageio.plugins.jpeg.JPEGImageWriteParam(null);
imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
imgWriteParams.setCompressionQuality(quality);
imgWriteParams.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
ColorModel colorModel = image.getColorModel();
imgWriteParams.setDestinationType(
new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16)));
try {
imgWrier.reset();
imgWrier.setOutput(ImageIO.createImageOutputStream(outArray));
imgWrier.write(null, new IIOImage(image, null, null), imgWriteParams);
} catch (Exception e) {
e.printStackTrace();
} finally {
imgWrier.dispose();
}
return outArray.toByteArray();
}
}
2.编写接口
ImageController代码如下:
package com.example.demo.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.demo.util.ImageUtil;
import com.example.demo.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Slf4j
@RestController
@RequestMapping("/image")
public class ImageController {
@PostMapping("/compressPic")
public R compressPic(MultipartFile file, String jsonObject) throws IOException {
if (file == null || file.isEmpty()) {
return R.error("文件不能为空,请检查!");
}
TimeInterval timer = DateUtil.timer();
JSONObject json = JSONUtil.parseObj(jsonObject);
String targetImg = "D:\\work\\test-gmaya\\image\\" + IdUtil.simpleUUID() + ".jpg";
File destImageFile = new File(targetImg);
FileUtil.writeBytes(file.getBytes(), destImageFile);
String isPressText = json.getStr("isPressText");
if ("0".equals(isPressText)) {
String pressText = json.getStr("pressText");
if(StrUtil.isEmpty(pressText)){
return R.error("水印文字不能为空,请检查!");
}
ImageUtil.pressText(pressText, targetImg);
}
String isCompress = json.getStr("isCompress");
if ("0".equals(isCompress)) {
byte[] bytes = ImageUtil.compressPic(file.getBytes());
FileUtil.writeBytes(bytes, destImageFile);
}
long interval = timer.interval();
log.info("图片处理总耗时:{}{}", interval, "ms");
return R.data(targetImg);
}
}
3.测试接口
总结
问题: 选择图片过大,导致失败
The field file exceeds its maximum permitted size of 1048576 bytes.
解决办法:
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
|