1. 程式人生 > >java中pdf檔案的管理(pdf檔案轉png檔案,base64傳輸檔案以及刪除)

java中pdf檔案的管理(pdf檔案轉png檔案,base64傳輸檔案以及刪除)

這幾天根據需求做了一個小demo,從中學習了一些java中pdf檔案的管理和檔案轉base64,主要包括以下幾個方面:

1.前端上傳影像檔案,把影像檔案儲存到指定的路徑下,然後如果是pdf檔案,把pdf檔案轉換為對應的png檔案儲存到pdf檔案儲存地址同級的指定資料夾中,同時保留原pdf檔案,如下圖:  pdf檔案和其對應的png檔案所在的資料夾 pdf檔案對應的png檔案(pdf檔案和與之對應的png檔名相同,例如:123.pdf對應123.png)                                                               2.影像檔案轉為base64編碼傳給前臺 3.影像檔案的刪除,如果是pdf檔案,同時把pdf檔案和其對應的png檔案刪除。   引入jar包: 
  pdf檔案轉png使用pdfbox.jar,maven地址:使用的是2.0.12版本
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.12</version>
        </dependency>

影像檔案轉為base64編碼使用java自帶的BASE64Encoder

  程式碼部分:

前端上傳檔案的儲存:

@RequestMapping("upLoadImgs")
@ResponseBody
public String upLoadAgreementsImg(HttpServletResponse response, HttpServletRequest request) throws Exception {

    //獲取前臺傳輸的檔案資料
    MultipartHttpServletRequest mreq = (MultipartHttpServletRequest) request;
    JSONObject rt = new JSONObject();
    
//預設儲存成功,失敗時再修改對應狀態 rt.put("status",0); rt.put("message","檔案儲存成功"); //上傳的合同影像列表 Iterator<String> fileNames = mreq.getFileNames(); MultipartFile file = null; String fileName = null; //檔案儲存地址,從配置檔案中獲取 :F:\imgs String folderPath = ResourceBundle.getBundle("systemconfig").getString("imagesDownloadPath"); //自定義影像檔案的名字(以當前系統時間+編碼區分) String imgName = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"); //用來區分同次上傳多個檔案的命名計數器01,02,03 int count = 1; //迴圈存入前端傳來的影像檔案 while (fileNames.hasNext()) { String countStr = "0"; fileName = (String) fileNames.next(); file = mreq.getFile(fileName); if (file == null) { logger.info("影像件上傳;檔案已損壞,請稍後再試"); rt.put("status",1); rt.put("message", "檔案已損壞,請稍後再試"); } //獲取前臺傳參檔名 fileName = file.getOriginalFilename(); //建立上傳檔案目錄 File folder = new File(folderPath); if (!folder.exists()) { folder.mkdirs(); } //獲取檔案的字尾名 String extension = fileName.substring(fileName.lastIndexOf(".")); //儲存的檔名 String saveName = imgName + countStr + Integer.toString(count++); String savePath = folderPath + File.separator + saveName + extension; try { file.transferTo(new File(savePath)); } catch (IOException e) { e.printStackTrace(); rt.put("status",1); rt.put("message", "檔案儲存失敗"); } //如果上傳的是pdf檔案,轉換為png檔案 if(extension.equals(".pdf")){ //轉換為jpg檔案 try { pdf2Png(savePath,folderPath,300,1); }catch (IOException e) { e.printStackTrace(); rt.put("status",1); rt.put("message", "pdf縮圖儲存失敗"); } } logger.info("file path:" + savePath); } return rt.toJSONString(); }

pdf檔案轉為png檔案,並將轉換後的png檔案儲存到pdf同級指定資料夾中:

這裡需要注意的是,使用PDDocument 物件轉換pdf檔案後,使用該物件的close()方法關閉,不然會導致對應的pdf檔案時出現因檔案被佔用而導致無法刪除。

/**
     * 把pdf檔案轉換為jpg檔案同步儲存到伺服器上
     * @param savePath    儲存的pdf檔案路徑
     * @param folderPath  檔案所在的資料夾
     * @param dpi   轉換後的檔案清晰度,
     * @param flag   轉換的pdf檔案頁數,為0時轉換全部頁數,也可以指定轉換頁數
     * @throws Exception
     */
    private void pdf2Png (String savePath,String folderPath,int dpi,int flag) throws  Exception {
        //獲取pdf檔案
        File file = new File(savePath);
        PDDocument pdDocument;
        //建立生成的檔案儲存路徑
        String newFolderPath = folderPath +File.separator+ "thumbnail";
        File folder = new File(newFolderPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        //轉換新的檔名,123.pdf轉換為123.png
        int dot = file.getName().lastIndexOf(".");
        String imgName = file.getName().substring(0, dot);
        pdDocument = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(pdDocument);
        int pages = pdDocument.getNumberOfPages();
        //確定要列印的頁數
        if (flag > 0) {
            if (flag < pages) {
                pages = flag;
            }
        }
        //生成新的檔案
        StringBuffer imgFilePath = null;
        for (int i = 0; i < pages; i++) {
            String imgSavePath = newFolderPath + File.separator + imgName;
            imgFilePath = new StringBuffer();
            imgFilePath.append(imgSavePath);
//            因為只轉換1頁,所以生成的圖片只有一張,不用分開命名,如果轉換多頁pdf檔案到多個png圖片,須加上命名區分
//            imgFilePath.append("-");
//            imgFilePath.append(String.valueOf(i + 1));
            imgFilePath.append(".png");
            File dstFile = new File(imgFilePath.toString());
            BufferedImage image = renderer.renderImageWithDPI(i, dpi);
            //引入一個輸出流,方便關閉,不然會因為檔案被佔用而導致無法刪除
            OutputStream ops = new FileOutputStream(dstFile);
            ImageIO.write(image, "png", dstFile);
            pdDocument.close();
            ops.close();
        }
    }

       根據檔案路徑查詢該路徑下的所有影像檔案,組裝成json返回給前臺,注意的是pdf檔案和其對應的png檔案組裝在同一個JsonObject中,方便前臺顯示:

  /**
     * 
     * @param  imgPath 要查詢的檔案路徑
     * @return      返回對應的查詢狀態值和檔案對應的base64編碼
     * @throws Exception
     */
    public String queryAgreementsImgByProvOid(String imgPath) throws Exception {
        JSONObject rt = new JSONObject();
        //預設狀態為查不到資料,查到資料後修改為0
        rt.put("status",1);
        String filePath = "";
        //伺服器儲存地址為null直接返回查詢失敗
        if(!StringUtil.isEmpty(imgPath)) {
            File file = new File(filePath);
            //判斷該路徑是否存在
            if (!file.exists()) {
                rt.put("message", "沒有相應的影像件");
            } else {
                File[] files = file.listFiles();
                //多個檔案放在json數組裡
                JSONArray imgArray = new JSONArray();
                for (int i = 0; i < files.length; i++) {
                    if (files[i].isFile()) {
                        JSONObject imgJson = new JSONObject();
                        String imgName = files[i].getName();
                        String imgBASE64Encoder = Base64Util.img2BASE64Encoder(files[i]);
                        //如果是pdf檔案,把對應的png、檔案也轉為base64編碼傳給前臺
                        if (imgName.endsWith(".pdf")) {
                            //找到對應的png檔案的檔案地址
                            StringBuffer imgPngFileName = new StringBuffer();
                            imgPngFileName.append(filePath + File.separator + "thumbnail");
                            int dot = imgName.lastIndexOf(".");
                            imgPngFileName.append(File.separator + imgName.substring(0, dot) + ".png");
                            File pngFile = new File(imgPngFileName.toString());
                            //如果不存在,返回給前臺對應的狀態碼
                            if(!pngFile.exists()){
                                imgJson.put("thumbnail", "");
                            }else {
                                String pngBASE64Encoder = Base64Util.img2BASE64Encoder(pngFile);
                                imgJson.put("thumbnail", pngBASE64Encoder);
                            }
                        }
                          //組裝進json物件裡,方便返回給前臺
                        imgJson.put("fileName", imgName);
                        imgJson.put("fileValue", imgBASE64Encoder);
                        imgArray.add(imgJson);
                    }
                }
                if (imgArray.size() != 0) {
                    rt.put("status", 0);
                    rt.put("imgs", imgArray);
                } else {
                    rt.put("message", "沒有相應的影像件");
                }
            }
        }else {
            rt.put("message", "沒有相應的影像件");
        }
        return rt.toJSONString();
    }

       其中Base64Util.img2BASE64Encoder(pngFile)的程式碼如下:

 /**
     * 圖片轉為base64編碼,其他檔案也是通用的
     * @param file    要轉換的檔案
     * @return
     * @throws Exception
     */
    public static String img2BASE64Encoder(File file) throws  Exception{

        InputStream in = null;
        byte[] data = null;
        try {
            // 讀取圖片位元組陣列
            in = new FileInputStream(file);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64編碼過的位元組陣列字串
        return encoder.encode(data);

    }

根據路徑刪除該路徑下的選中的影像檔案,pdf檔案同時刪除與之對應的png檔案:

/**
     * 
     * @param delFilePath  要刪除的檔案路徑
     * @param fileNames   要刪除的檔案列表
     * @return     根據刪除狀態返回給前臺對應的狀態值
     * @throws Exception
     */
    public String delImgsByPath(String delFilePath, List<String> fileNames) throws Exception {
        JSONObject rt = new JSONObject();
        rt.put("status",0);
        rt.put("message", "檔案刪除成功");

        if(StringUtil.isEmpty(delFilePath) || fileNames.size()==0){
            rt.put("status", 1);
            rt.put("message", "刪除資料出錯,請聯絡相關人員");
        }
        //根據檔案路徑開始刪除
        if(!StringUtil.isEmpty(delFilePath)){
            String fulllFileName = "";
            for (int j = 0; j < fileNames.size(); j++) {

                String name = fileNames.get(j);
                //要刪除的檔案完整路徑名
                fulllFileName = delFilePath + File.separator + name;
                File delFile = new File(fulllFileName);
                if (delFile.exists()) {
                    if (!delFile.delete()) {
                        rt.put("status", 1);
                        rt.put("message", "檔案刪除失敗,請稍後重試");
                    }
                }
                if (name.endsWith(".pdf")) {
                    StringBuffer imgPngFileName = new StringBuffer();
                    imgPngFileName.append(delFilePath + File.separator + "thumbnail");
                    int dot = name.lastIndexOf(".");
                    imgPngFileName.append(File.separator + name.substring(0, dot) + ".png");
                    File pngFile = new File(imgPngFileName.toString());
                    if(pngFile.exists()){
                        if (!pngFile.delete()) {
                            rt.put("status", 1);
                            rt.put("message", "檔案刪除失敗,請稍後重試");
                        }
                    }
                }
            }
        }

        return rt.toJSONString();
    }

以上就是對影像檔案進行增,刪,查的功能的程式碼,其中pdf檔案由於檔案型別特殊,前段無法顯示pdf檔案的縮圖進行選中刪除操作,所以把pdf檔案轉換為png檔案後再儲存到指定的資料夾中,查詢的時候一起組裝為一個json物件裡傳給前臺,方便前臺的顯示,刪除時同時把pdf檔案對應的png檔案刪除,防止佔用記憶體空間。關於pdf檔案在前段無法生成縮圖這個問題的解決方案,還在持續的學習中,如果有好的建議,歡迎留言大家一起學習。