spring boot:實現圖片文件上傳並生成縮略圖(spring boot 2.3.1)


一,為什么要給圖片生成縮略圖?

1, 用戶上傳的原始圖片如果太大,不能直接展示在網站頁面上,

   因為不但流費server的流量,而且用戶打開時非常費時間,

   所以要生成縮略圖。

2,服務端管理圖片要注意的幾點:

   第一點:縮略圖要與原圖分開存儲,
   然后通過符號鏈接方式允許前端訪問,

   否則原圖被直接訪問仍然存在浪費流量的問題,

   有圖片版權的公司也不允許外部直接訪問原圖

   第二點:圖片名字要加上一些隨機的數字,

             避免被窮舉訪問

   第三點:圖片要分目錄存放,通常每1000張保存到一個目錄,

            因為大量的圖片如果存放到同一個目錄下,

            打開時會非常慢或者不能打開,

            不利於我們對文件進行管理           

 

說明:劉宏締的架構森林是一個專注架構的博客,地址:https://www.cnblogs.com/architectforest

         對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/

說明:作者:劉宏締 郵箱: 371125307@qq.com

 

二,演示項目的相關信息

1,項目的地址:

https://github.com/liuhongdi/imagemodify

 

2,項目原理:

   實現了圖片的文件上傳,

   並用ImageMagick給非gif圖片生成縮略圖,

    用ffmpeg生成gif圖片的縮略圖

 

3,項目結構:如圖:

 

 

三,ImageMagick/ffmpeg工具軟件的安裝

1,dnf安裝ImageMagick

[root@blog head]# dnf install ImageMagick 

說明:注意軟件包名字中I和M均為大寫

檢查軟件是否安裝成功?

[root@blog head]# whereis convert
convert: /usr/bin/convert /usr/share/man/man1/convert.1.gz 

 

2,安裝ffmpeg

安裝rpmfusion庫

[root@blog ~]# dnf install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm 

下載sdl庫

[root@blog ~]# wget http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/SDL2-2.0.8-7.el8.x86_64.rpm

安裝sdl庫:

[root@blog ~]# rpm -ivh SDL2-2.0.8-7.el8.x86_64.rpm
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:SDL2-2.0.8-7.el8                 ################################# [100%]

安裝ffmpeg

[root@blog ~]# dnf install ffmpeg 

 

四,配置文件說明:

1,application.properties

#upload
spring.servlet.multipart.maxFileSize=30MB
spring.servlet.multipart.maxRequestSize=30MB

說明:指定上傳文件的最大限制,

默認大小是1M

 

2,nginx訪問文件的host配置:file.conf

server {
    listen       81;
    server_name  file.lhdtest.com;
    root         /data/file/html;
     location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
           root /data/file/html;
           expires 24h;
       }
    index         index.html;
    access_log      /data/logs/nginxlogs/file.access_log;
    error_log       /data/logs/nginxlogs/file.error_log;
}

 

3,Constant.java

    //圖片從nginx訪問時的host
    public static final String IMAGES_URL_HOST = "http://127.0.0.1:81";
    //默認原始圖片的路徑
    public static final String IMAGES_ORIG_DIR = "/data/file/html/images";
    //縮略圖的文件路徑
    public static final String IMAGES_TMB_DIR = "/data/file/html/tmb";
    //縮略圖的長邊長度
    public static final String IMAGES_TMB_LONG = "300";
    //分頁顯示時每頁的顯示數量
    public static final int IMAGES_PAGE_SIZE = 5;
    //ImageMagick命令的安裝路徑
    public static final String IMAGEMAGICK_DIR = "/usr/bin";
    //ffmpeg的完整路徑
    public static final String FFMPEG_CMD = "/usr/bin/ffmpeg";

4,創建保存圖片信息的數據表:

CREATE TABLE `image_service` (
 `image_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '圖片id',
 `image_sn` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '圖片編號',
 `image_type` varchar(10) NOT NULL DEFAULT '' COMMENT '圖片類型',
 `title` varchar(200) NOT NULL DEFAULT '' COMMENT '標題',
 `size` int(11) NOT NULL DEFAULT '0' COMMENT '文件大小',
 `width` int(11) NOT NULL DEFAULT '0' COMMENT '寬度',
 `height` int(11) NOT NULL DEFAULT '0' COMMENT '高度',
 `add_time` datetime NOT NULL DEFAULT '2019-11-01 01:01:01' COMMENT '添加時間 ',
 `staff_id` int(11) NOT NULL DEFAULT '0' COMMENT '添加的用戶',
 PRIMARY KEY (`image_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='圖片信息表'

 

五,java代碼說明:

1,ImageModifyUtil.java

public class ImageModifyUtil {
    //按指定的邊長生成縮略圖
    public static boolean image_resize_by_long_side(String orig_path, String dest_path, String long_size,String imageType) {
        try {
        List<String> command = new ArrayList<>();
         String command_one = "";
        if (imageType.equals("gif")) {
            //計算得到目標寬高
            File gifFile = new File(orig_path);
            int gifWidth = 0;
            int gifHeight = 0;
            try {
                BufferedImage imageBuffer = ImageIO.read(gifFile);
                if (imageBuffer != null) {//如果image=null 表示上傳的不是圖片格式
                    gifWidth = imageBuffer.getWidth();
                    gifHeight = imageBuffer.getHeight();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            int destWidth = 0;
            int destHeight = 0;
            if (gifWidth > gifHeight) {
                destWidth = Integer.parseInt( long_size );
                destHeight = (destWidth*gifHeight) / gifWidth;
            } else if  (gifWidth == gifHeight) {
                destWidth = Integer.parseInt( long_size );
                destHeight = destWidth;
            } else {
                destHeight = Integer.parseInt( long_size );
                destWidth = (destHeight*gifWidth) / gifHeight;
            }
            command_one = Constant.FFMPEG_CMD+" -i "+orig_path+" -s "+destWidth+"x"+destHeight+" "+dest_path+" 2>&1";
        } else {
            command_one = Constant.IMAGEMAGICK_DIR+"/convert -size "+long_size+"x"+long_size+" -resize "+long_size+"x"+long_size+" +profile '*' -quality 85 "+orig_path+" "+dest_path+" 2>&1";
        }
        //System.out.println(command_one);
        command.add("sh");
        command.add("-c");
        command.add(command_one);
        // 執行cmd命令
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(command);
        Process process = builder.start();
        return true;
        } catch (Exception e) {
            System.out.println("save ioexception");
            e.printStackTrace();
            return false;
        }
    }
}

這個類用來生成縮略圖

說明:gif圖生成縮略圖時,我們要幫助ffmpeg計算出准確的長和寬

2,ImageDownUtil.java

public class ImageDownUtil {
    //按指定的路徑下載一張圖片
    public static void downImageByLocalPath(HttpServletResponse response,String fullImagePath,String imageName) {
        File file = new File(fullImagePath);
        if (file.exists()) {
            response.setContentType("application/force-download");// 設置強制下載不打開
            response.addHeader("Content-Disposition", "attachment;fileName=" + imageName);// 設置文件名
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                System.out.println("success");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //按指定的文件路徑顯示圖片
    public static ResponseEntity<InputStreamResource> dispImageByLocalPath(String fullImagePath) {
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.IMAGE_JPEG);
        Path path = Paths.get(fullImagePath);
        InputStream content;
        try {
            content = Files.newInputStream(path);
            return new ResponseEntity<>(new InputStreamResource(content), header, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.notFound().build();
        }
    }
}

這個類用來下載圖片和用java顯示一張圖片

 

六,效果測試

測試前的注意事項:

測試前要先啟動服務:

mysql

nginx

1,圖片上傳:

訪問:

http://127.0.0.1:8080/image/imageadd

如圖:

2,查看已上傳的圖片列表

訪問:

http://127.0.0.1:8080/image/imagelist

如圖:

 

七,查看spring boot的版本

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.1.RELEASE)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM