java中pdf檔案的管理(pdf檔案轉png檔案,base64傳輸檔案以及刪除)
阿新 • • 發佈:2018-12-16
這幾天根據需求做了一個小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包:<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檔案在前段無法生成縮圖這個問題的解決方案,還在持續的學習中,如果有好的建議,歡迎留言大家一起學習。