本周三、周四、周五封装了一个基于SpringBoot的图片上传组件。功能流程如下:
1、前台页面有一个“选择文件”按钮,点击选择一张图片后,在前台界面进行显示。
2、双击显示出来的图片,前台使用cropper图片裁剪插件,将裁剪信息(裁剪起始点坐标 x,y,裁剪宽度width,裁剪高度height)以及上传的图片文件,传给后台。
3、后台对图片进行裁剪,再将裁剪后的图片进行压缩,把原图路径、裁剪后图片路径、压缩后图片路径、base64编码存入数据库。(同时后台将这三种图片保存到本地 D:/images/ 路径下)
4、后台将压缩后的图片路径传给前台。
5、前台接收到这个路径,在页面上进行显示。由于此时显示的是压缩的图片,如果用户想看原图(裁剪后图片的原图),点击该图片,携带这个图片路径请求后台接口。
6、后台接收到压缩图片路径,select数据库,找到裁剪后图片路径,返回给前台。
7、前台接收到这个原图片路径,在页面进行显示。
一、SpringBoot自定义静态资源映射
将一些动态维护的文件,放在服务器磁盘的某个目录下(项目目录之外),并且通过SpringBoot服务进行访问。
实现类继承WebMvcConfigurerAdapter并重写方法addResourceHandlers,将磁盘上文件存放的绝对路径映射,就可以通过访问SpringBoot服务来访问文件了。
- @Configuration
- public class WebAppConfig extends WebMvcConfigurerAdapter {
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/myImages/**").addResourceLocations("file:D:/images/");
- super.addResourceHandlers(registry);
- }
- }
这样就将D盘上的images目录映射到myImages路径下,这个 myImages 是随意的一个命名。
假如在D盘images目录下有一个test.jpg图片,那么通过访问 http://localhost:8080/myImages/test.jpg
就可以访问到该图片了。
二、Java实现图片裁剪、使用Thumbnailator工具对图片进行压缩。
height。
1、controller层代码:
-
-
-
-
-
-
-
-
- @RequestMapping(value = "/cutImage", method = RequestMethod.POST, headers = "Accept=application/json")
- @ResponseBody
- public HttpResponseEntity cutImage(MultipartFile file,
- int x, int y, int width, int height) {
- HttpResponseEntity httpResponseEntity = new HttpResponseEntity();
- try {
-
- String strResult = imgUploadService.cutImage(file, x, y, width, height);
- httpResponseEntity.setMessage("成功");
- httpResponseEntity.setCode("200");
- httpResponseEntity.setData(strResult);
-
- } catch (Exception e) {
- e.printStackTrace();
- httpResponseEntity.setCode("602");
- httpResponseEntity.setMessage("失败");
- }
- return httpResponseEntity;
- }
2、service层代码:
在本方法中使用uuid为图片重命名。
在本方法中实现了对图片的裁剪、等比例压缩。此处压缩使用的是Thumbnailator工具,压缩质量很高。但是按照
Thumbnails.of(new_path_img)
.scale(1f)//图片长宽大小
.outputQuality(0.1f)//图片质量
.toFile(compress_img_path);
这个方法实现的压缩,内存大小依旧很大。
- @Override
-
-
-
-
-
-
-
-
-
- public String cutImage(MultipartFile file, int x, int y, int width, int height) throws IOException {
-
- String filename = file.getOriginalFilename();
-
- String suffixName = filename.substring(filename.lastIndexOf("."));
-
- String name = UUIDUtil.getOneUUID();
- filename = name + suffixName;
-
- String filePath = "D:/images/";
-
- String path_img = filePath + filename;
- File dest = new File(path_img);
- if (!dest.getParentFile().exists()) {
- dest.getParentFile().mkdirs();
- }
- try {
- file.transferTo(dest);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- ImgUploadEntity imgUploadEntity = new ImgUploadEntity();
- imgUploadEntity.setImgPath(filename);
-
- FileInputStream is = null;
- ImageInputStream iis = null;
- try {
-
- if (!new File(path_img).exists()) {
- return "失败";
- }
-
- is = new FileInputStream(path_img);
-
- String ext = path_img.substring(path_img.lastIndexOf(".") + 1);
-
- Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(ext);
- ImageReader reader = it.next();
-
- iis = ImageIO.createImageInputStream(is);
-
- reader.setInput(iis, true);
-
- ImageReadParam param = reader.getDefaultReadParam();
-
- Rectangle rect = new Rectangle(x, y, width, height);
-
- param.setSourceRegion(rect);
-
- BufferedImage bi = reader.read(0, param);
-
- String name1 = UUIDUtil.getOneUUID();
- String newFileName = name1 + suffixName;
- String new_path_img = filePath + newFileName;
-
- File tempOutFile = new File(new_path_img);
- if (!tempOutFile.exists()) {
- tempOutFile.mkdirs();
- }
- ImageIO.write(bi, ext, tempOutFile);
- imgUploadEntity.setNewImgPath(newFileName);
-
-
- String compressImgPath = UUIDUtil.getOneUUID() + suffixName;
- String compress_img_path = filePath + compressImgPath;
-
-
-
-
-
-
-
-
-
- if(tempOutFile.length() < 51200){
- compressImgPath = newFileName;
- compress_img_path = new_path_img;
- imgUploadEntity.setCompressImgPath(compressImgPath);
- File noCompressFile = new File(compress_img_path);
- if (!noCompressFile.exists()) {
- tempOutFile.mkdirs();
- }
- }
- else {
-
- if (suffixName.equals(".png")) {
- Thumbnails.of(new_path_img)
- .scale(1f)
- .outputFormat("jpg")
- .toFile(filePath + name1);
- }
- Thumbnails.of(new_path_img)
- .scale(1f)
- .outputQuality(0.1f)
- .toFile(compress_img_path);
- imgUploadEntity.setCompressImgPath(compressImgPath);
- }
-
-
-
-
-
-
- imgUploadEntityMapper.insertImgPath(imgUploadEntity);
-
- return compressImgPath;
-
- } catch (Exception e) {
- e.printStackTrace();
- return "失败";
- } finally {
- try {
- if (is != null) {
- is.close();
- }
- if (iis != null) {
- iis.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- return "失败";
- }
- }
- }
可以实现
图片压缩
的另一种方法:这种方法需要传入想要压缩后的图片长、宽。我认为这个方法也很好,可以指定大小。
- /**
- * @param inputFile 源文件
- * @param outFile 生成文件
- * @param width 指定宽度
- * @param height 指定高度
- * @param proportion 是否等比例操作
- * @描述 —— 是否等比例缩放图片
- */
- public static boolean compressImg(String inputFile, String outFile,
- int width, int height, boolean proportion) {
- try {
- // 获得源文件
- File file = new File(inputFile);
- if (!file.exists()) {
- return false;
- }
- Image img = ImageIO.read(file);
- // 判断图片格式是否正确
- if (img.getWidth(null) == -1) {
- return false;
- } else {
- int newWidth;
- int newHeight;
- // 判断是否是等比缩放
- if (proportion == true) {
- // 为等比缩放计算输出的图片宽度及高度
- double rate1 = ((double) img.getWidth(null))
- / (double) width + 0.1;
- double rate2 = ((double) img.getHeight(null))
- / (double) height + 0.1;
- // 根据缩放比率大的进行缩放控制
- double rate = rate1 > rate2 ? rate1 : rate2;
- newWidth = (int) (((double) img.getWidth(null)) / rate);
- newHeight = (int) (((double) img.getHeight(null)) / rate);
- } else {
- newWidth = width; // 输出的图片宽度
- newHeight = height; // 输出的图片高度
- }
-
- BufferedImage tag = new BufferedImage((int) newWidth,
- (int) newHeight, BufferedImage.TYPE_INT_RGB);
-
- /*
- * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的,优先级比速度高
- 生成的图片质量比较好但速度慢
- */
- tag.getGraphics().drawImage(
- img.getScaledInstance(newWidth, newHeight,
- Image.SCALE_SMOOTH), 0, 0, null);
- FileOutputStream out = new FileOutputStream(outFile);
- // JPEGImageEncoder可适用于其他图片类型的转换
- JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
- encoder.encode(tag);
- out.close();
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- return true;
- }
本组件原计划将压缩后的图片转化成base64编码,存到数据库,前台请求图片时,给前台返回这个base64编码,但是由于Thumbnailato工具压缩完图片后,图片依旧很大,导致base64码过长,不利于前后台数据交互,所以后来改成直接传图片路径了。
把图片转base64编码的代码贴出来:
- public String codeBase64(String inputFile) {
-
- InputStream in = null;
- byte[] data = null;
-
- try {
- in = new FileInputStream(inputFile);
- data = new byte[in.available()];
- in.read(data);
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- String strBase64 = new String(Base64.encodeBase64(data));
-
- return strBase64;
-
- }
Thumbnailato使用时需要添加依赖
- <dependency>
- <span style="white-space:pre;"> </span><groupId>net.coobird</groupId>
- <artifactId>thumbnailator</artifactId>
- <version>0.4.8</version>
- </dependency>
以上代码就是Java实现对图片上传、裁剪、压缩的代码实现。
本人还是一枚Java小白,如有不对的地方,请大家多多指正。
参考自:
http://blog.csdn.net/Colton_Null/article/details/78255970
http://blog.csdn.net/wangpeng047/article/details/19624993
http://blog.csdn.net/wangpeng047/article/details/19624993