java實現上傳自動生成縮略圖


最近做項目需求,前台上傳文件等后台自動處理縮略圖,在統一文件管理頁面展示

使用了一些工具和方法實現了對圖片,文檔,視頻的縮率圖獲取,

首先是依賴如下

        <!-- pdf生成縮率圖依賴 -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.24</version>
        </dependency>
        <!--   操作視頻獲取縮略圖依賴     -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>4.0.2-1.4.3</version>
        </dependency>

視頻轉換ffmeg也可以使用安裝軟件的方式調用,大批量轉換時效率更高,在本需求中使用的是異步多線程處理的方式
圖片直接使用javax自帶的ImageIO操作即可,文檔類的轉換思路是將doc,docx,xls等文檔類型轉化為pdf再使用pdfbox獲取第一張生成為縮率圖

public class FileToThumbnail {
 /**
     * <p>Title: thumbnailImage</p>
     * <p>Description: 根據圖片路徑生成縮略圖 </p>
     * @param imagePath    原圖片路徑
     * @param w            縮略圖寬
     * @param h            縮略圖高
     * @param prevfix    生成縮略圖的前綴
     * @param force      是否強制按照寬高生成縮略圖(如果為false,則生成最佳比例縮略圖)
     */
    public void getThumbnailForPic(String imagePath, int w, int h, String prevfix, boolean force) throws IOException {
        File imgFile = new File(imagePath);
        if(imgFile.exists()){
                // ImageIO 支持的圖片類型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
                String types = Arrays.toString(ImageIO.getReaderFormatNames());
                String suffix = null;
                // 獲取圖片后綴
                if(imgFile.getName().indexOf(".") > -1) {
                    suffix = imgFile.getName().substring(imgFile.getName().lastIndexOf(".") + 1);
                }
                // 類型和圖片后綴全部小寫,然后判斷后綴是否合法
                if(suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()) < 0){
                    System.out.println("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
                    return ;
                }
                System.out.println("target image's size, width:{"+w+"}, height:{"+h+"}.");
                Image img = ImageIO.read(imgFile);
                if(!force){
                    // 根據原圖與要求的縮略圖比例,找到最合適的縮略圖比例
                    int width = img.getWidth(null);
                    int height = img.getHeight(null);
                    if((width*1.0)/w < (height*1.0)/h){
                        if(width > w){
                            h = Integer.parseInt(new java.text.DecimalFormat("0").format(height * w/(width*1.0)));
                        }
                    } else {
                        if(height > h){
                            w = Integer.parseInt(new java.text.DecimalFormat("0").format(width * h/(height*1.0)));
                        }
                    }
                }
                BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics g = bi.getGraphics();
                g.drawImage(img, 0, 0, w, h, Color.LIGHT_GRAY, null);
                g.dispose();
                String p = imgFile.getPath();
                // 將圖片保存在原目錄並加上前綴
                ImageIO.write(bi, suffix, new File(p.substring(0,p.lastIndexOf(File.separator)) + File.separator + prevfix +imgFile.getName()));
        }
    }


    /**
     * 通過PDFbox生成文件的縮略圖
     *
     * @param filePath:文件路徑
     * @param outPath:輸出圖片路徑
     * @throws IOException
     */
    public  String getThumbnailForPdf(String filePath, String outPath) throws IOException {
        // 利用PdfBox生成圖像
        PDDocument pdDocument = PDDocument.load(new File(filePath));
        PDFRenderer renderer = new PDFRenderer(pdDocument);
        // 構造圖片
        BufferedImage img_temp = renderer.renderImageWithDPI(0, 30, ImageType.RGB);
        ImageIO.write(img_temp,"png",new File(outPath));
        pdDocument.close();
        return outPath;
    }
    /**
     * @description //生成視頻縮略圖的URL地址
     * @param sourcePath 保存路徑
     * @return String 保存路徑
     */
    public String getThumbnailForVideo(InputStream inputStream,String sourcePath) throws IOException {
        File targetFile = new File(sourcePath);

        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(inputStream);
        ff.start();
        // 視頻總幀數
        int videoLength = ff.getLengthInFrames();
        Frame f  = null;
        int i = 0;
        while (i < videoLength) {
            // 過濾前20幀,因為前20幀可能是全黑的
            // 這里看需求,也可以直接根據幀數取圖片
            f = ff.grabFrame();
            if (i > 20 && f.image != null) {
                break;
            }
            i++;
        }
        int owidth = f.imageWidth;
        int oheight = f.imageHeight;
        // 對截取的幀進行等比例縮放
        int width = 300;
        int height = (int) (((double) width / owidth) * oheight);
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage fecthedImage = converter.getBufferedImage(f);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
                0, 0, null);
        ImageIO.write(bi, "png", targetFile);
        // 查看stop源碼會自動關流
        ff.stop();
        return sourcePath;

    }


}

文檔轉pdf的好用的工具基本付費,如果有win環境推薦jcob,其他的自行百度或使用poi,easypoi等試一下(前面博客有處理過word)
后續處理思路是建立任務類,根據分類需求進行不同處理,在上傳完成后調度異步任務即可,也可以用消息隊列,也加一個定期執行定時任務,可以防止文件服務器掉線導致丟失處理(做好錯誤處理就可以不用)


免責聲明!

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



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