這幾天根據需求做了一個小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文件在前段無法生成縮略圖這個問題的解決方案,還在持續的學習中,如果有好的建議,歡迎留言大家一起學習。