先上展示效果
文件上傳頁面,頁面比較粗糙勿怪,
雙擊打開圖中畫紅線的word文檔,進行電子書預覽
實現功能有四步走
1、前端實現word文件上傳(本人用的是webuploader上傳控件,個人感覺挺好用)
2、前端頁面以turn.js的電子書控件展示(純html5、css與JQuery實現)
3、后端將上傳來的word文件轉換成pdf文件 參考:https://www.cnblogs.com/xxyfhjl/p/6773786.html
4、再將pdf文件轉成一張一張的圖片
https://www.cnblogs.com/xxyfhjl/p/6773786.html
上代碼
前端上傳頁面代碼
①HTML樣式

<div class="wrapper wrapper-content" style="margin-top: 5px;"> <div class="row"> <div class="col-lg-3" style="width: 25%;float:left;position:relative;min-height:1px;padding-left: 15px;padding-right:15px;"> <div class="ibox float-e-margins" style="font-size:13px;height:510px;margin-left: 12px;"> <div class="ibox-content" style="height: 100%;"> <div class="file-manager" style="height: 100%;"> <div class="hr-line-dashed"></div> <div class="form-group form-inline"> <div id="filePicker" style="width: 100%;">上傳</div> </div> <button class="btn btn-danger btn-block" onclick="backUp();">返回</button> <div class="hr-line-dashed"></div> <h5>文件類型</h5> <ul class="folder-list" style="padding: 0"> <li><a onclick="searchSameType(0);"><i class="fa fa-folder"></i> 全部 </a></li> <li><a onclick="searchSameType(1);"><i class="fa fa-folder"></i> 文本文件 </a></li> <li><a onclick="searchSameType(2);"><i class="fa fa-folder"></i> 圖片 </a></li> <li><a onclick="searchSameType(3);"><i class="fa fa-folder"></i> 視頻 </a></li> <li><a onclick="searchSameType(4);"><i class="fa fa-folder"></i> 音頻 </a></li> </ul> <h5 class="tag-title">標簽</h5> <ul class="tag-list" style="padding: 0" id="type_id"> <li><a href="">word</a></li> <li><a href="">excel</a></li> <li><a href="">pdf</a></li> <li><a href="">mp3</a></li> <li><a href="">mp4</a></li> <li><a href="">avi</a></li> </ul> <div class="clearfix"></div> </div> </div> </div> </div> <div class="col-lg-9" style="width: 75%;float:left;position:relative;min-height:1px;padding-left: 15px;padding-right:15px;"> <div class="row" id="row_id"></div> </div> <div id="uploadProgress" class="mydiv1" style="height: 170px;width: 330px;z-index: 999;position: absolute;right: -330px;bottom: 5px;"> <div style="width: 100%;height:5px;background-color: #3C85EB"></div> <div style="font-size: 20px;padding:5px;">上傳進度</div> <div style="height: 1px;width: 100%;background-color: #000;"></div> <div id="fileList" class="uploader-list;" style="overflow:auto;height:120px;"> </div> </div> </div> </div>
②js上傳代碼

//上傳文件 function upload(LOG_ID){ //管理員才有上傳按鈕 if(roleType==0){ $("#filePicker").hide(); return; } var user_id = getcookie("userId"); var update_url= apiUrl+"app_riverFileFj/fileUpload?LOG_ID="+LOG_ID+"&USER_ID="+userId; // 初始化Web Uploader uploader = WebUploader.create({ // 自動上傳。 auto: false, // swf文件路徑 swf:'static/js/webuploader/Uploader.swf', // 文件接收服務端。 server: update_url, // 選擇文件的按鈕。可選。 pick: {id:'#filePicker', //選擇文件的按鈕 multiple:true}, //允許可以同時選擇多個圖片 //限制傳輸文件類型 accept: { title: 'file',//描述 extensions: '*',//類型 mimeTypes: '*'//mime類型 } }); // 當有文件添加進來的時候 uploader.on( 'fileQueued', function( file ) { $("#uploadProgress").animate({right:'20px'},"slow").fadeIn("slow"); var fileAllName=file.name; var fileName=""; var fileType=fileAllName.substring(fileAllName.indexOf(".")); fileAllName=fileAllName.substring(0,fileAllName.indexOf(".")); if(fileAllName.length>6){ fileName=fileAllName.substring(0,5); fileName=fileName+"..."+fileType; }else{ fileName=fileAllName+fileType; } var oneProgress= "<div id='" + file.id +"' class='item' >"+ "<div style='width: 40%;float:left;padding-left:3px;'>"+ "<h4 class='info'>"+ fileName +"</h4>"+ "</div>"+ "<div style='width: 60%;float:left;' id='"+file.id+"_bar'>"+ "</div>"+ "</div>"; $("#fileList").append(oneProgress); }); // 文件上傳過程中創建進度條實時顯示。 uploader.on( 'uploadProgress', function( file, percentage ) { var $li = $( '#'+file.id+"_bar" ), $percent = $li.find('.progress .progress-bar'); // 避免重復創建 if ( !$percent.length ) { $percent = $('<div class="progress progress-striped active">' + '<div class="progress-bar" role="progressbar" style="width: 0%">0%' + '</div>' + '</div>').appendTo( $li ).find('.progress-bar'); } var num=percentage.toFixed(3); $percent.css( 'width', percentage * 100 + '%' ).text("已上傳:"+num* 100 + '%'); }); // 文件上傳成功 uploader.on( 'uploadSuccess', function( file ) { $('#'+file.id).remove(); }); // 文件上傳失敗,顯示上傳出錯 uploader.on( 'uploadError', function( file ) { $( '#'+file.id ).find('p.state').text('上傳出錯'); }); // 完成上傳完 uploader.on( 'uploadComplete', function( file ) { $( '#'+file.id ).find('.progress').fadeOut(); $("#uploadProgress").animate({right:'-330px'},"slow",search()); }); $("#filePicker").on("change",function () { uploader.upload(); }); }
后端接受上傳文件代碼

/** * @athour:SZH * 2018年7月16日 下午4:14:08 * @description:上傳文件 * @param request * @param response * @throws UnsupportedEncodingException */ @RequestMapping("fileUpload") public void fileUpload(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{ try { PageData pd =this.getPageData(); String FILE_FOLDER=pd.getString("LOG_ID"); String USER_ID=pd.getString("USER_ID"); System.out.println("收到文件"); MultipartHttpServletRequest Murequest = (MultipartHttpServletRequest)request; Map<String, MultipartFile> files = Murequest.getFileMap();//得到文件map對象 //文件保存路徑 String logo_path = request.getSession().getServletContext().getRealPath("uploadFiles/file")+File.separator; for(MultipartFile file :files.values()){ String fileAllName=file.getOriginalFilename(); String TYPE= fileAllName.substring(fileAllName.lastIndexOf(".")+1); String fileName= fileAllName.substring(0,fileAllName.lastIndexOf(".")); //保存的文件名 String fileNewName=new Date().getTime()+"."+TYPE; String path=logo_path+FILE_FOLDER+"/"+fileNewName; File newFile=new File(path); if(!newFile.exists()){ newFile.mkdirs(); } file.transferTo(newFile); //將word文檔轉成HTML文件 String HtmlName =""; if(TYPE.equals("doc") || TYPE.equals("docx")) { String wordFilePath=logo_path+FILE_FOLDER + "/"+fileNewName; new Thread(()->{ office2Img(wordFilePath,1); } ).start(); }else if(TYPE.equals("ppt") || TYPE.equals("pptx")) { String wordFilePath=logo_path+FILE_FOLDER + "/"+fileNewName; new Thread(()->{ office2Img(wordFilePath,2); } ).start(); }else if(TYPE.equalsIgnoreCase("pdf")){ new Thread(()->{ PDF2ImageUtil.pdf2Image(newFile.getAbsolutePath(), logo_path+FILE_FOLDER, 300); } ).start(); } if(HtmlName.equals("")){ HtmlName=fileNewName; } //在數據庫中保存記錄 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); pd.put("FILE_FOLDER", FILE_FOLDER); pd.put("FILE_NAME", fileAllName); pd.put("FILE_TYPE", TYPE); pd.put("TM", sdf.format(date)); pd.put("PERSON", USER_ID); pd.put("URL", "uploadFiles/file/"+FILE_FOLDER+File.separator+fileNewName); pd.put("HTML_URL","uploadFiles/file/"+FILE_FOLDER+"/"+HtmlName); RiverFileFjService.saveFile(pd); } } catch (Exception e) { e.printStackTrace(); } } public void office2Img(String officeFilePath,Integer opt){ String pdfFile=""; if(opt==1){ pdfFile= Office2PDFUtil.word2PDF(officeFilePath); }else if(opt==2){ pdfFile= Office2PDFUtil.ppt2PDF(officeFilePath); } if(pdfFile!=""){ String dstImgFolder=pdfFile.substring(0,pdfFile.lastIndexOf("/")); PDF2ImageUtil.pdf2Image(pdfFile, dstImgFolder, 300); } }
兩個工具類
office轉pdf與pdf轉圖片

package com.hywy.util; import java.io.File; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; public class Office2PDFUtil { private static final Integer WORD_TO_PDF_OPERAND = 17; private static final Integer PPT_TO_PDF_OPERAND = 32; private static final Integer EXCEL_TO_PDF_OPERAND = 0; /** * @athour:SZH * 2018年7月27日 下午4:08:49 * @description:word轉pdf * @param wordFile * @return */ public static String word2PDF(String wordFile) { String pdfFile=wordFile.substring(0,wordFile.lastIndexOf("."))+".pdf"; ActiveXComponent app = null; System.out.println("開始轉換..."); // 開始時間 long start = System.currentTimeMillis(); try { // 打開word app = new ActiveXComponent("Word.Application"); // 設置word不可見,很多博客下面這里都寫了這一句話,其實是沒有必要的,因為默認就是不可見的,如果設置可見就是會打開一個word文檔,對於轉化為pdf明顯是沒有必要的 // app.setProperty("Visible", false); // 獲得word中所有打開的文檔 Dispatch documents = app.getProperty("Documents").toDispatch(); System.out.println("打開文件: " + wordFile); // 打開文檔 Dispatch document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch(); // 如果文件存在的話,不會覆蓋,會直接報錯,所以我們需要判斷文件是否存在 File target = new File(pdfFile); if (target.exists()) { target.delete(); } System.out.println("另存為: " + pdfFile); // 另存為,將文檔報錯為pdf,其中word保存為pdf的格式宏的值是17 Dispatch.call(document, "SaveAs", pdfFile, WORD_TO_PDF_OPERAND); // 關閉文檔 Dispatch.call(document, "Close", false); // 結束時間 long end = System.currentTimeMillis(); System.out.println("轉換成功,用時:" + (end - start) + "ms"); return pdfFile; } catch (Exception e) { System.out.println("轉換失敗" + e.getMessage()); return ""; } finally { // 關閉office if (app != null) { app.invoke("Quit", 0); } ComThread.Release(); } } public static String ppt2PDF(String pptFile) { String pdfFile=pptFile.substring(0,pptFile.lastIndexOf("."))+".pdf"; ActiveXComponent app = null; Dispatch ppt = null; System.out.println("開始轉換..."); // 開始時間 long start = System.currentTimeMillis(); try { ComThread.InitSTA(); app = new ActiveXComponent("PowerPoint.Application"); Dispatch ppts = app.getProperty("Presentations").toDispatch(); /* * call * param 4: ReadOnly * param 5: Untitled指定文件是否有標題 * param 6: WithWindow指定文件是否可見 * */ ppt = Dispatch.call(ppts, "Open", pptFile, true,true, false).toDispatch(); File target = new File(pdfFile); if (target.exists()) { target.delete(); } System.out.println("另存為: " + pdfFile); Dispatch.call(ppt, "SaveAs", pdfFile, PPT_TO_PDF_OPERAND); // ppSaveAsPDF為特定值32 //關閉文檔 Dispatch.call(ppt, "Close"); // 結束時間 long end = System.currentTimeMillis(); System.out.println("轉換成功,用時:" + (end - start) + "ms"); return pdfFile; } catch (Exception e) { e.printStackTrace(); return ""; } finally { if (app != null) { app.invoke("Quit"); } ComThread.Release(); } } }

package com.hywy.util; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; public class PDF2ImageUtil { /** * @athour:SZH * 2018年7月18日 下午7:18:11 * @description: * @param PdfFilePath PDF文件路徑 * @param dstImgFolder 圖片路徑 * @param dpi */ public static void pdf2Image(String PdfFilePath, String dstImgFolder, int dpi) { File file = new File(PdfFilePath); PDDocument pdDocument; try { String imgPDFPath = file.getParent(); int dot = file.getName().lastIndexOf('.'); String imagePDFName = file.getName().substring(0, dot); // 獲取圖片文件名 String imgFolderPath = null; if (dstImgFolder.equals("")) { imgFolderPath = imgPDFPath + File.separator + imagePDFName;// 獲取圖片存放的文件夾路徑 } else { imgFolderPath = dstImgFolder+ File.separator + imagePDFName; } if (createDirectory(imgFolderPath)) { pdDocument = PDDocument.load(file); PDFRenderer renderer = new PDFRenderer(pdDocument); /* dpi越大轉換后越清晰,相對轉換速度越慢 */ int pages = pdDocument.getNumberOfPages(); StringBuffer imgFilePath = null; for (int i = 0; i < pages; i++) { String imgFilePathPrefix = imgFolderPath +File.separator; imgFilePath = new StringBuffer(); imgFilePath.append(imgFilePathPrefix); imgFilePath.append(String.valueOf(i + 1)); imgFilePath.append(".png"); File dstFile = new File(imgFilePath.toString()); BufferedImage image = renderer.renderImageWithDPI(i, dpi); ImageIO.write(image, "png", dstFile); } System.out.println("PDF文檔轉PNG圖片成功!"); pdDocument.close(); } else { System.out.println("PDF文檔轉PNG圖片失敗:" + "創建" + imgFolderPath + "失敗"); } } catch (IOException e) { e.printStackTrace(); } } private static boolean createDirectory(String folder) { File dir = new File(folder); if (dir.exists()) { return true; } else { return dir.mkdirs(); } } }
電子書代碼

//雙擊查看文件 function showFileCont(file_url){ var fileType_url=file_url.substring(file_url.indexOf(".")); if(fileType_url.toLowerCase()==".doc" || fileType_url.toLowerCase()==".docx"){ //獲取圖片保存路徑 var imgUrl=file_url.substring(0,file_url.indexOf(".")); //獲取文件個數 var folderNum=getFolderNum(imgUrl); window.location.href="read_file/slider.html?id="+id+"&li="+li+"&imgUrl="+imgUrl+"&folderNum="+folderNum+"&reach_name="+reach_name+"&roleType="+roleType; //}else if(fileType_url.toLowerCase()==".ppt" || fileType_url.toLowerCase()==".pptx"){ // //獲取圖片保存路徑 // var imgUrl=file_url.substring(0,file_url.indexOf(".")); // //獲取文件個數 // var folderNum=getFolderNum(imgUrl); // window.location.href="read_file/slider.html?id="+id+"&li="+li+"&imgUrl="+imgUrl+"&folderNum="+folderNum+"&reach_name="+reach_name+"&roleType="+roleType; }else{ window.location.href="file_view/readFile.html?"+file_url; } }
簡單對turns.js給的demo進行了簡單的修改,在這里就不貼代碼了,官網地址
http://www.turnjs.com/
使用到的包
pdfbox-2.0.11.jar ,fontbox-2.0.11.jar,jacob.jar,jacob-1.19-x64.dll
注意:
本方法只能運行在windows上