昨晚搭建環(huán)境都花了好一會(huì)時(shí)間旷余,主要在浪費(fèi)在了安裝 openoffice 這個(gè)依賴(lài)環(huán)境上(Mac 需要手動(dòng)安裝)绢记。
然后,又一步一步功能演示正卧,記錄蠢熄,調(diào)試項(xiàng)目,并且簡(jiǎn)單研究了一下核心代碼之后才把這篇文章寫(xiě)完炉旷。
另外签孔,這篇文章我還會(huì)簡(jiǎn)單分析一下項(xiàng)目核心代碼叉讥。
如果有幫助,歡迎點(diǎn)贊/再看鼓勵(lì)饥追,我會(huì)開(kāi)心很久 ?( ′???` )比心
項(xiàng)目介紹
官方是這樣介紹 kkFileView 的:
kkFileView 是使用 spring boot 打造文件文檔在線(xiàn)預(yù)覽項(xiàng)目解決方案图仓,支持 doc、docx但绕、ppt救崔、pptx、xls捏顺、xlsx六孵、zip、rar草丧、mp4狸臣、mp3 以及眾多類(lèi)文本如 txt、html昌执、xml烛亦、java、properties懂拾、sql煤禽、js、md岖赋、json檬果、conf、ini唐断、vue选脊、php、py脸甘、bat恳啥、gitignore 等文件在線(xiàn)預(yù)覽
簡(jiǎn)單來(lái)說(shuō) kkFileView 就是常見(jiàn)的文件類(lèi)型的在線(xiàn)預(yù)覽解決方案。
總的來(lái)說(shuō)我覺(jué)得 kkFileView 是一個(gè)非常棒的開(kāi)源項(xiàng)目丹诀,在線(xiàn)文件預(yù)覽這個(gè)需求非常常見(jiàn)钝的。感謝開(kāi)源!
下面铆遭, 我站在一個(gè)“上帝”的角度從多個(gè)維度來(lái)評(píng)價(jià)一下 kkFileView:
- 代碼質(zhì)量一般硝桩,有很多可以?xún)?yōu)化的地方比如:
-
Controller
層代碼嵌套太多邏輯 - 沒(méi)有進(jìn)行全局異常處理(代碼中是直接返回錯(cuò)誤信息的 json 數(shù)據(jù)給前端,我并不推薦這樣做)
- 返回值不需要通過(guò)
ObjectMapper
轉(zhuǎn)換為 JSON 格式(ResponseEntity
+@RestController
就行了) - ......
-
- 使用的公司比較多枚荣,說(shuō)明項(xiàng)目整體功能還是比較穩(wěn)定和成熟的碗脊!
- 代碼整體邏輯還是比較清晰的,比較容易看懂棍弄,給作者們點(diǎn)個(gè)贊望薄!
環(huán)境搭建
克隆項(xiàng)目
通過(guò)以下命令即可將項(xiàng)目克隆到本地:
git clone https://gitee.com/kekingcn/file-online-preview.git
安裝 OpenOffice
office 類(lèi)型的文件的預(yù)覽依賴(lài)了 OpenOffice 疟游,所以我們首先要安裝 OpenOffice(Windows 下已內(nèi)置,Linux 會(huì)自動(dòng)安裝痕支,Mac OS 下需要手動(dòng)安裝)颁虐。
下面演示一下如何在 Mac 上安裝 OpenOffice。
你可以通過(guò)以下命令安裝最新版的 OpenOffice:
brew cask install openoffice
不過(guò)卧须,這種方式下載可能會(huì)比較慢另绩,你可以直接去官網(wǎng)下載 dmg 安裝包。
官方下載地址:https://www.openoffice.org/download/
很多小伙伴就要問(wèn)了:OpenOffice 是什么呢花嘶?
OpenOffice 是 Apache 旗下的一款開(kāi)源免費(fèi)的文字處理軟件笋籽,支持 Windows、Liunx椭员、OS X 等主流操作系統(tǒng)车海。
OpenOffice 和 Windows 下 office 辦公軟件有點(diǎn)類(lèi)似,不過(guò)其實(shí)開(kāi)源免費(fèi)的隘击。
啟動(dòng)項(xiàng)目
運(yùn)行FilePreviewApplication
的 main 方法侍芝,服務(wù)啟動(dòng)后,訪(fǎng)問(wèn)http://localhost:8012/ 會(huì)看到如下界面埋同,代表服務(wù)啟動(dòng)成功州叠。
使用
我們首先上傳了 3 個(gè)不同的類(lèi)型的文件來(lái)分別演示一下圖片、PDF凶赁、Word 文檔的預(yù)覽咧栗。
圖片的預(yù)覽
kkFileView 支持 jpg,jpeg虱肄,png致板,gif 等多種格式圖片的預(yù)覽,還包括了翻轉(zhuǎn)咏窿,縮放圖片等操作可岂。
圖片的預(yù)覽效果如下。
Word 文檔的預(yù)覽
kkFileView 支持 doc翰灾,docx 文檔預(yù)覽。
另外稚茅,根據(jù) Word 大小以及網(wǎng)速問(wèn)題纸淮, Word 預(yù)覽提供了兩種模式:
- 每頁(yè) Word 轉(zhuǎn)為圖片預(yù)覽
- 整個(gè) Word 文檔轉(zhuǎn)成 PDF,再預(yù)覽 PDF亚享。
兩種模式的適用場(chǎng)景如下
- 圖片預(yù)覽 :Word 文件大(加載 PDF 速度比較慢)的情況咽块。
- PDF 預(yù)覽 :內(nèi)網(wǎng)訪(fǎng)問(wèn)(加載 PDF 速度比較快)的情況。
圖片預(yù)覽模式預(yù)覽效果如下:
PDF 預(yù)覽模式預(yù)覽效果如下:
PDF 文檔的預(yù)覽
kkFileView 支持 PDF 文檔預(yù)覽欺税。類(lèi)似 Word 文檔預(yù)覽侈沪, PDF 預(yù)覽提供了兩種模式:
- 每頁(yè) Word 轉(zhuǎn)為圖片預(yù)覽
- 整個(gè) Word 文檔轉(zhuǎn)成 PDF揭璃,再預(yù)覽 PDF。
由于和 Word 文檔的預(yù)覽展示效果一致亭罪,這里就不放圖片了瘦馍。
文件預(yù)覽核心代碼分析
API 層
文件預(yù)覽調(diào)用的接口是 /onlinePreview
。
通過(guò)分析 /onlinePreview
接口我們發(fā)現(xiàn)应役, 后端接收到預(yù)覽請(qǐng)求之后情组,會(huì)從 URL 和請(qǐng)求中篩選出自己需要的信息比如文件后綴、文件名箩祥。
之后會(huì)調(diào)用FilePreview
類(lèi) 的 filePreviewHandle()
方法院崇。filePreviewHandle()
方法是實(shí)現(xiàn)文件預(yù)覽的核心方法。
@RequestMapping(value = "/onlinePreview")
public String onlinePreview(String url, Model model, HttpServletRequest req) {
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
req.setAttribute("fileKey", req.getParameter("fileKey"));
model.addAttribute("pdfDownloadDisable", ConfigConstants.getPdfDownloadDisable());
model.addAttribute("officePreviewType", req.getParameter("officePreviewType"));
FilePreview filePreview = previewFactory.get(fileAttribute);
logger.info("預(yù)覽文件url:{}袍祖,previewType:{}", url, fileAttribute.getType());
return filePreview.filePreviewHandle(url, model, fileAttribute);
}
FilePreview
是文件預(yù)覽接口底瓣,不同的文件類(lèi)型的預(yù)覽都實(shí)現(xiàn)了 FilePreview
接口,并實(shí)現(xiàn)了 filePreviewHandle()
方法蕉陋。
文件預(yù)覽接口
public interface FilePreview {
String filePreviewHandle(String url, Model model, FileAttribute fileAttribute);
}
不同的文件類(lèi)型的預(yù)覽都實(shí)現(xiàn)了 FilePreview
接口捐凭,如下圖所示。
不同文件類(lèi)型的預(yù)覽都會(huì)實(shí)現(xiàn) FilePreview
接口寺滚,然后重寫(xiě)filePreviewHandle()
方法柑营。比如: OfficeFilePreviewImpl
這個(gè)主要負(fù)責(zé)處理 office 文件的預(yù)覽、PdfFilePreviewImpl
主要負(fù)責(zé)處理 pdf 文件的預(yù)覽村视。
文件預(yù)覽具體實(shí)現(xiàn)分析
下面我們以 office 文件的預(yù)覽為入口來(lái)分析官套。
首先要明確的是 excel 類(lèi)型的預(yù)覽是通過(guò)將 excel 文件轉(zhuǎn)換為 HTML 實(shí)現(xiàn)的,其他類(lèi)型 office 文件的預(yù)覽是通過(guò)將文件轉(zhuǎn)換為 PDF 或者是 圖片的方式來(lái)預(yù)覽的蚁孔。
舉個(gè)例子奶赔。我們上傳了一份名為 武漢市文化市場(chǎng)管理辦法.docx
的 Word 文件并預(yù)覽的話(huà),jodconverter-web/src/main/file
路徑下會(huì)生成兩個(gè)相關(guān)文件杠氢,這兩個(gè)文件分別對(duì)應(yīng)了我們提到的 PDF 預(yù)覽 和 圖片預(yù)覽這兩種方式站刑。
武漢市文化市場(chǎng)管理辦法.pdf
- 由 Word 文件所轉(zhuǎn)化得到的一系列圖片
我們以一個(gè)名為 武漢市文化市場(chǎng)管理辦法.docx
的文件來(lái)舉例說(shuō)明一下代碼中是如何做的。
通過(guò)分析代碼鼻百, 我們定位到了 OfficeFilePreviewImpl
這個(gè)主要負(fù)責(zé)處理 office 文件預(yù)覽的類(lèi)绞旅。
/**
* 處理office文件
*/
@Service
public class OfficeFilePreviewImpl implements FilePreview {
}
我們來(lái)簡(jiǎn)單分析一下 OfficeFilePreviewImpl
類(lèi)中實(shí)現(xiàn)預(yù)覽的核心方法是 filePreviewHandle
。
說(shuō)明:這部分代碼的邏輯不夠清晰温艇,還可以抽方法優(yōu)化以讓人更容易讀懂因悲,感興趣的小伙伴可以自己動(dòng)手重構(gòu)一下,然后去給作者提個(gè) PR勺爱。
@Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
// 1.獲取預(yù)覽類(lèi)型(image/pdf/html)晃琳,用戶(hù)請(qǐng)求中傳了officePreviewType參數(shù)就取參數(shù)的,沒(méi)傳取系統(tǒng)默認(rèn)(image)
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
// 2.獲取 URL 地址
String baseUrl = BaseUrlFilter.getBaseUrl();// http://localhost:8012/
// 3.獲取圖片相關(guān)信息
String suffix=fileAttribute.getSuffix();//文件后綴如docx
String fileName=fileAttribute.getName();//文件名如:武漢市文化市場(chǎng)管理辦法.docx
// 4. 判斷是否為 html 格式預(yù)覽也就是判斷文件否為 excel
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
// 5. 將文件的后綴名更換為 .pdf 或者 .html(excel文件的情況)
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
// 6. 轉(zhuǎn)換后的文件輸出的文件夾如 file-online-preview/jodconverter-web/src/main/file/武漢市文化市場(chǎng)管理辦法.pdf)
String outFilePath = FILE_DIR + pdfName;
// 7 .判斷之前是否已轉(zhuǎn)換過(guò),如果轉(zhuǎn)換過(guò)卫旱,直接返回人灼,否則執(zhí)行轉(zhuǎn)換
// 文件第一次被預(yù)覽的時(shí)候會(huì)首先對(duì)文件進(jìn)行緩存處理
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
String filePath;
// 下載文件
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
if (0 != response.getCode()) {
model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg());
return "fileNotSupported";
}
filePath = response.getContent();
if (StringUtils.hasText(outFilePath)) {
officeToPdf.openOfficeToPDF(filePath, outFilePath);
if (isHtml) {
// 對(duì)轉(zhuǎn)換后的文件進(jìn)行操作(改變編碼方式)
fileUtils.doActionConvertedFile(outFilePath);
}
if (ConfigConstants.isCacheEnabled()) {
// 加入緩存
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
}
}
}
// 8.根據(jù)預(yù)覽類(lèi)型officePreviewType,選擇不同的預(yù)覽方式
// 比如,如果預(yù)覽類(lèi)型officePreviewType為pdf則進(jìn)行pdf方式預(yù)覽
if (!isHtml && baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, pdfName, outFilePath, pdfUtils, OFFICE_PREVIEW_TYPE_IMAGE);
}
model.addAttribute("pdfUrl", pdfName);
return isHtml ? "html" : "pdf";
}
項(xiàng)目地址: https://github.com/kekingcn/kkFileView
我整理了一份優(yōu)質(zhì)原創(chuàng)PDF資源免費(fèi)分享給大家顾翼,大部分內(nèi)容都是我的原創(chuàng)投放,少部分來(lái)自朋友。
<img src="https://cdn.jsdelivr.net/gh/javaguide-tech/blog-images/2020-10/image-20201012105544846.png" style="zoom:50%;" />
<img src="https://cdn.jsdelivr.net/gh/javaguide-tech/blog-images/2020-10/image-20201012105608336.png" alt="image-20201012105608336" style="zoom:50%;" />
下載地址:https://cowtransfer.com/s/fbed14f0c22a4d 暴构。
我的開(kāi)源項(xiàng)目推薦
- JavaGuide :「Java學(xué)習(xí)+面試指南」一份涵蓋大部分Java程序員所需要掌握的核心知識(shí)跪呈。準(zhǔn)備 Java 面試,首選 JavaGuide取逾!
- guide-rpc-framework :A custom RPC framework implemented by Netty+Kyro+Zookeeper.(一款基于 Netty+Kyro+Zookeeper 實(shí)現(xiàn)的自定義 RPC 框架-附詳細(xì)實(shí)現(xiàn)過(guò)程和相關(guān)教程)
- jsoncat :仿 Spring Boot 但不同于 Spring Boot 的一個(gè)輕量級(jí)的 HTTP 框架
- programmer-advancement :程序員應(yīng)該有的一些好習(xí)慣+面試必知事項(xiàng)耗绿!
- springboot-guide :Not only Spring Boot but also important knowledge of Spring(不只是SpringBoot還有Spring重要知識(shí)點(diǎn))
- awesome-java :Collection of awesome Java project on Github(Github 上非常棒的 Java 開(kāi)源項(xiàng)目集合).
作者介紹: Github 70k Star 項(xiàng)目 JavaGuide(公眾號(hào)同名) 作者。每周都會(huì)在公眾號(hào)更新一些自己原創(chuàng)干貨砾隅。公眾hao后臺(tái)回復(fù)“1”領(lǐng)取Java工程師必備學(xué)習(xí)資料+面試突擊pdf误阻。