使用pdf.js線上預覽 PDF (本地檔案,伺服器檔案)
前言
不使用外掛直接進行pdf預覽時,對於小檔案沒有任何問題,但在預覽一個305M,近400頁的pdf檔案時,開啟pdf直接拉到最後幾頁,會造成瀏覽器崩潰,於是嘗試使用pdf.js的外掛方式進行pdf預覽,解決大檔案瀏覽器崩潰的問題。
1、下載地址
http://mozilla.github.io/pdf.js/
主要用到裡邊的 viewer.js 和 viewer.html 檔案
2、開啟資料夾,把這兩個檔案放程序序,一個是 build,一個是 web 資料夾,建議整個資料夾都放進去!到這差不多安裝過程就 ok 了,viewer.html 檔案裡邊有預設的 PDF 檔案
測試方法window.open(' ../pdf/web/viewer.html')
3、找到剛剛放入程式的檔案,開啟 web 檔案目錄,開啟 viewer.js 檔案找到他預設展示的 PDF 檔案的路徑改為 value:’’ ( 也可以不修改 )
4、想要呼叫這個 JS 來預覽 PDF ,方法跟上方測試方法差不多,只不過多加了一個條件
呼叫方法:windows.open("/pdf/web/viewer.html?file=file.pdf");
這個方法只能讀取你 web 目錄下的檔案,如果想要讀取你本地檔案或者伺服器檔案 就 通過流的方式輸出
5、獲取本地/伺服器檔案
前端寫法:通過點選事件觸發預覽
previewURL: 專案地址路徑
filePath: 要開啟的專案
encodeURIComponent:用於 url 特殊字元的轉譯(比如 : ; / ? : @ & = + $ , # 這些用於分隔 URI 元件的標點符號)
// 點選呼叫預覽方法
function xx(filePath){
var previewURL= "127.0.0.1:8080/";
window.open('../pdf/web/viewer.html?file='+encodeURIComponent(previewURL+"/test?url="+filePath));
}
後端寫法:拿到檔案地址,通過流的方式輸出到移動端頁面顯示
// 通過檔案流的方式預覽 PDF 檔案
@RequestMapping(value = "test")
public void pdfStreamHandeler(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
// 獲取路徑
String filePath = request.getParameter("url");
File file = new File(filePath);
byte[] data = null;
try {
// 編輯請求頭部資訊
// 解決請求頭跨域問題(IE相容性 也可使用該方法)
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/pdf");
FileInputStream input = new FileInputStream(file);
data = new byte[input.available()];
input.read(data);
response.getOutputStream().write(data);
input.close();
} catch (Exception e) {
}
}
下面是我的專案中的呼叫方式:
/**
* 預覽PDF
*/
@RequiresPermissions("dagl:pdf")
@Log(title = "PDF預覽", businessType = BusinessType.DELETE)
@GetMapping("/pdfPreview/{dh}")
public String pdfPreview(@PathVariable("dh") String dh, ModelMap mmap)
{
mmap.put("pdf_url", fileReadUrl+dazlxxb.getPdfUrl());
return prefix + "/pdfPreview";
}
<!DOCTYPE html>
<html style="height: 100%" lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<link th:href="@{/css/update.css}" rel="stylesheet"/>
<th:block th:include="include :: header('PDF預覽')"/>
<th:block th:include="include :: datetimepicker-css"/>
</head>
<body class="white-bg">
<iframe style="width: 100%;height: 100%;" frameborder="0" id="pdfView"></iframe>
</body>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:inline="javascript">
var pdf_url = [[${pdf_url}]];
var prefix = "/dagl";
$('#pdfView').attr('src', '/pdf/web/viewer.html?file=' + encodeURIComponent(prefix +"/pdfStreamHandeler?pdf_url=" + pdf_url));
</script>
</html>
// 通過檔案流的方式預覽 PDF 檔案
@RequestMapping(value = "pdfStreamHandeler")
public void pdfStreamHandeler(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
// 獲取路徑
String filePath = request.getParameter("pdf_url");
try {
if(StringUtils.isNotBlank(filePath)) {
byte[] data = fileDfsUtil.downLoadFile(filePath);
// 編輯請求頭部資訊
// 解決請求頭跨域問題(IE相容性 也可使用該方法)
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("application/pdf");
response.getOutputStream().write(data);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Component
public class FileDfsUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class);
@Resource
private FastFileStorageClient storageClient ;
/**
* 上傳檔案
*/
public String upload(MultipartFile multipartFile,String fileName) throws Exception{
StorePath storePath = storageClient.uploadFile(multipartFile.getInputStream(), multipartFile.getSize(),
FilenameUtils.getExtension(fileName), null);
return storePath.getFullPath() ;
}
/**
* 刪除檔案
*/
public String deleteFile(String fileUrl) {
if (StringUtils.isEmpty(fileUrl)) {
return "fileUrl == >>檔案路徑為空...";
}
try {
StorePath storePath = StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
return e.getMessage();
}
return "OK";
}
public byte[] downLoadFile(String filePath){
StorePath storePath = StorePath.parseFromUrl(filePath);
return storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
}
}
6、測試介面
7、常見問題
1).跨域錯誤:file origin does not match viewer’s
解決方式:找到 viewer.js 中下方的這段程式碼註釋掉
2).找不到檔案錯誤:這個問題原因是因為沒有獲取到你本地或者伺服器檔案,也就是 pdf > web 目錄裡沒有這個 pdf ,因為它預設是獲取這個目錄下的 pdf 檔案
解決方式:獲取本地檔案或者伺服器檔案路徑,通過流的方式輸出到頁面上
3).檔案損壞無法顯示問題:出現這個問題一般都是你的 url 沒有進行轉碼就直接請求到瀏覽器了,然後 url 存在的特殊字元會會讓瀏覽器誤認為你這個不是一個完整的連結
解決方式:檢視前端訪問的路徑是否使用 encodeURIComponent 轉碼
8、如何隱藏外掛自帶的下載和列印功能?開啟 viewer.html 檔案,搜尋<button id="download"
在這個 button 按鈕加上一個屬性style="visibility:hidden"
就 ok 了,如下圖