1. 程式人生 > >基於SpringBoot的圖片上傳元件,實現圖片裁剪、Thumbnailator壓縮的功能

基於SpringBoot的圖片上傳元件,實現圖片裁剪、Thumbnailator壓縮的功能

本週三、週四、週五封裝了一個基於SpringBoot的圖片上傳元件。功能流程如下:

1、前臺頁面有一個“選擇檔案”按鈕,點選選擇一張圖片後,在前臺介面進行顯示。

2、雙擊顯示出來的圖片,前臺使用cropper圖片裁剪外掛,將裁剪資訊(裁剪起始點座標 x,y,裁剪寬度width,裁剪高度height)以及上傳的圖片檔案,傳給後臺。

3、後臺對圖片進行裁剪,再將裁剪後的圖片進行壓縮,把原圖路徑、裁剪後圖片路徑、壓縮後圖片路徑、base64編碼存入資料庫。(同時後臺將這三種圖片儲存到本地 D:/images/ 路徑下)

4、後臺將壓縮後的圖片路徑傳給前臺。

5、前臺接收到這個路徑,在頁面上進行顯示。由於此時顯示的是壓縮的圖片,如果使用者想看原圖(裁剪後圖片的原圖),點選該圖片,攜帶這個圖片路徑請求後臺介面。

6、後臺接收到壓縮圖片路徑,select資料庫,找到裁剪後圖片路徑,返回給前臺。

7、前臺接收到這個原圖片路徑,在頁面進行顯示。

一、SpringBoot自定義靜態資源對映

將一些動態維護的檔案,放在伺服器磁碟的某個目錄下(專案目錄之外),並且通過SpringBoot服務進行訪問。

實現類繼承WebMvcConfigurerAdapter並重寫方法addResourceHandlers,將磁碟上檔案存放的絕對路徑對映,就可以通過訪問SpringBoot服務來訪問檔案了。

  1. @Configuration  
  2. public class WebAppConfig extends WebMvcConfigurerAdapter {  
  3.     @Override  
  4.     public void addResourceHandlers(ResourceHandlerRegistry registry) {  
  5.         registry.addResourceHandler("/myImages/**").addResourceLocations("file:D:/images/");  
  6.         super.addResourceHandlers(registry);  
  7.     }  
  8. }  
這樣就將D盤上的images目錄對映到myImages路徑下,這個 myImages 是隨意的一個命名。
假如在D盤images目錄下有一個test.jpg圖片,那麼通過訪問 http://localhost:8080/myImages/test.jpg 
就可以訪問到該圖片了。

二、Java實現圖片裁剪、使用Thumbnailator工具對圖片進行壓縮。

height。

1、controller層程式碼:

  1. /** 
  2.  * 影象切割(按指定起點座標和寬高切割) 
  3.  * @param file 源影象檔案 
  4.  * @param x 目標切片起點座標X 
  5.  * @param y 目標切片起點座標Y 
  6.  * @param width 目標切片寬度 
  7.  * @param height 目標切片高度 
  8.  */
  9. @RequestMapping(value = "/cutImage", method = RequestMethod.POST, headers = "Accept=application/json")  
  10. @ResponseBody
  11. public HttpResponseEntity cutImage(MultipartFile file,  
  12.                                    int x, int y, int width, int height) {  
  13.     HttpResponseEntity httpResponseEntity = new HttpResponseEntity();  
  14.     try {  
  15.         String strResult = imgUploadService.cutImage(file, x, y, width, height);  
  16.         httpResponseEntity.setMessage("成功");  
  17.         httpResponseEntity.setCode("200");  
  18.         httpResponseEntity.setData(strResult);  
  19.     } catch (Exception e) {  
  20.         e.printStackTrace();  
  21.         httpResponseEntity.setCode("602");  
  22.         httpResponseEntity.setMessage("失敗");  
  23.     }  
  24.     return httpResponseEntity;  
  25. }  
2、service層程式碼:

在本方法中使用uuid為圖片重新命名。

在本方法中實現了對圖片的裁剪、等比例壓縮。此處壓縮使用的是Thumbnailator工具,壓縮質量很高。但是按照

Thumbnails.of(new_path_img)
        .scale(1f)//圖片長寬大小
.outputQuality(0.1f)//圖片質量
.toFile(compress_img_path);
這個方法實現的壓縮,記憶體大小依舊很大。
  1. @Override
  2.     /** 
  3.      * @param srcFile原始檔 
  4.      * @param outFile輸出檔案 
  5.      * @param x座標 
  6.      * @param y座標 
  7.      * @param width寬度 
  8.      * @param height高度 
  9.      * @描述 —— 裁剪圖片 
  10.      */
  11.     public String cutImage(MultipartFile file, int x, int y, int width, int height) throws IOException {  
  12.         //得到上傳時的檔名
  13.         String filename = file.getOriginalFilename();  
  14.         //獲取檔案字尾名
  15.         String suffixName = filename.substring(filename.lastIndexOf("."));  
  16.         //獲取uuid作為檔名
  17.         String name = UUIDUtil.getOneUUID();  
  18.         filename = name + suffixName;  
  19.         //儲存地址
  20.         String filePath = "D:/images/";  
  21.         //圖片路徑
  22.         String path_img = filePath + filename;  
  23.         File dest = new File(path_img);  
  24.         if (!dest.getParentFile().exists()) {  
  25.             dest.getParentFile().mkdirs();  
  26.         }  
  27.         try {  
  28.             file.transferTo(dest);  
  29.         } catch (IOException e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.         ImgUploadEntity imgUploadEntity = new ImgUploadEntity();  
  33.         imgUploadEntity.setImgPath(filename);  
  34.         FileInputStream is = null;  
  35.         ImageInputStream iis = null;  
  36.         try {  
  37.             // 如果源圖片不存在
  38.             if (!new File(path_img).exists()) {  
  39.                 return"失敗";  
  40.             }  
  41.             // 讀取圖片檔案
  42.             is = new FileInputStream(path_img);  
  43.             // 獲取檔案格式
  44.             String ext = path_img.substring(path_img.lastIndexOf(".") + 1);  
  45.             // ImageReader解碼指定格式
  46.             Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(ext);  
  47.             ImageReader reader = it.next();  
  48.             // 獲取圖片流
  49.             iis = ImageIO.createImageInputStream(is);  
  50.             // 輸入源中的影象將只按順序讀取
  51.             reader.setInput(iis, true);  
  52.             // 描述如何對流進行解碼
  53.             ImageReadParam param = reader.getDefaultReadParam();  
  54.             // 圖片裁剪區域
  55.             Rectangle rect = new Rectangle(x, y, width, height);  
  56.             // 提供一個 BufferedImage,將其用作解碼畫素資料的目標
  57.             param.setSourceRegion(rect);  
  58.             // 使用所提供的 ImageReadParam 讀取通過索引 imageIndex 指定的物件
  59.             BufferedImage bi = reader.read(0, param);  
  60.             // 儲存新圖片
  61.             String name1 = UUIDUtil.getOneUUID();  
  62.             String newFileName = name1 + suffixName;  
  63.             String new_path_img = filePath + newFileName;  
  64.             File tempOutFile = new File(new_path_img);  
  65.             if (!tempOutFile.exists()) {  
  66.                 tempOutFile.mkdirs();  
  67.             }  
  68.             ImageIO.write(bi, ext, tempOutFile);  
  69.             imgUploadEntity.setNewImgPath(newFileName);  
  70.             //為壓縮後圖片建立路徑
  71.             String compressImgPath = UUIDUtil.getOneUUID() + suffixName;  
  72.             String compress_img_path = filePath + compressImgPath;  
  73.             //等比壓縮圖片,使用Java
  74. //            boolean flag = compressImg(new_path_img, compress_img_path,100,100,true);
  75.             /* 
  76.             * 壓縮圖片,使用Thumbnails工具 
  77.             * 先判斷圖片大小,如果小於50 kb(51200位元組)不進行壓縮 
  78.             * file.length()方法最大隻能獲取2g的檔案大小,但是前臺傳給後臺圖片最大為10M,所以此處不必擔心 
  79.             */
  80.             if(tempOutFile.length() < 51200){