1. 程式人生 > >PDF.js 2種使用方式,跨域使用

PDF.js 2種使用方式,跨域使用

前言

因為工作需要,開發移動端線上閱讀PDF文件。所以找到了PDF.js,但PDF檔案是儲存在另外獨立伺服器,所以常規使用PDF.js會存在問題,經過搜尋查詢,實踐解決了問題。

這邊提供嘗試過的2種有效方法

1.繪製頁面

html 

<div> <h1><a href="javascript:void(0)" target="_blank" onclick="showPdf()">顯示pdf文件</a></h1> <div id="container" style="display: none;"> <
div class="lightbox"></div> <div id="pop" class="pop"></div> </div></div>

js

<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="./pdfjs/build/pdf.js" type="text/javascript"></script> <script src
="./pdfjs/build/pdf.worker.js" type="text/javascript"></script> <script type="text/javascript"> function showall(url, page, id) { PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) { pdf.getPage(page).then(function getPageHelloWorld(page) { var
scale = 1.0; var viewport = page.getViewport(scale); var canvas = document.getElementById(id); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); }); }
function showPdf() { var url = 'http://otdddh8nn.bkt.clouddn.com/yxxj.pdf';//pdf檔案地址 $("#container").show(); $("#pop").empty(); PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) { pages = pdf.numPages; for(var i = 1; i < pdf.numPages; i++) { var id = 'page-id-' + i; $("#pop").append('<canvas id="' + id + '"></canvas>'); showall(url, i, id); } }); }
</script>

引入 pdf.worker.js 、 pdf.js  兩個檔案和jq,通過呼叫檔案api繪製PDF頁面.

特點 可以根據自己需要構建頁面,對手機網速有要求。

備註 蘋果6 ios11系統會報Unhandled Promise Rejection: UnexpectedResponseException: Unexpected server response (206) while retrieving PDF  可能和儲存伺服器不支援斷點續傳有關係(有知道的大佬可以告訴我下)所以後面改用以下方法。

2.使用viewer.html

html

<iframe style="width:100%;height:100%;" src="./pdfjs/web/viewer.html?pdf_url=http://otdh8nn.bkt.clouddn.com/yxxj.pdf">
</iframe>

viewer.js 註釋掉 DEFAULT_URL

新建viewer.php 

<?phpecho file_get_contents($_GET['pdf_url']);

viewer.html 頁面底部新增

<script>
    var DEFAULT_URL = './viewer.php?pdf_url='+getQueryStringByName('pdf_url');
    function getQueryStringByName(name){ var result = location.search.match(new RegExp("[\?\&]" + name+ "=([^\&]+)","i")); if(result == null || result.length < 1){ return ""; } return result[1];    }</script>

在頁面新增 iframe 標籤開啟viewer.html  傳引數pdf_url 值為pdf地址 ;

在viewer.html 修改預設地址default_url 為viewer.php,傳引數pdf_url ;

而在viewer.php頁面將pdf_url 網址的pdf檔案讀取成字串返回給前臺顯示 。

特點 速度很快,上方有選單,可以根據自己需要修改註釋掉了選單部分功能。

單獨傳參可以開啟頁面,實現跨域訪問

http://localhost/web/pdfjs/web/viewer.html?pdf_url =http://otq6dd8nn.bkt.clouddn.com/yxxj.pdf

補充 

個人使用的是 pdfjs-1.9 版本 包含web和build2個資料夾

官方FAQ
Can I load a PDF fromanother server (cross domain request)?能否從其它伺服器讀取pdf檔案(跨域訪問)?

Notby default, but it is possible. PDF.js runs with the same permissions as anyother JavaScript code, which means it cannot do cross origin requests (see Same origin policyand an example).There are some possible ways to get around this such as using CORS(seealso unsafeheaders issueand Access-Control-Expose-Headersissue) or setting up a proxy on your server thatwill feed PDF.js the PDF file. Both workarounds are out of the scope of thePDF.js project and we will not provide code to do either.

不預設,但它是可能的。 PDF.js執行具有相同許可權的任何其他JavaScript程式碼,這意味著它不能跨出自身請求(見同根同源的政策和示例) 。有一些可能的方法來解決這個問題,如使用CORS (seealsounsafe headers issueandAccess-Control-Expose-Headersissue),或者設定你的伺服器上的代理,將PDF檔案提供給PDF.js。這兩種解決方法都出了PDF.js專案的範圍,我們將不提供程式碼,請執行。

第二種方法實際上就是用php自身先讀取文件再開啟,網上有說用讀取檔案流方式可行,原理一致

我個人php 沒有仔細研究   但java一般都是採用這個方法。

也貼一下程式碼

function getStream(){     $filepath = 'http://otq68ddnn.bkt.clouddn.com/yxxj.pdf';    $fp = fopen($filepath,"r");    Header('Content-Type: application/pdf');    header('Access-Control-Allow-Origin:*');    //Header("Content-type: application/octet-stream");    Header("Accept-Ranges: bytes");    Header("Content-Disposition: attachment; filename=yxxj.pdf");    $buffer = 1024;    while (!feof($fp)) {    $file_con = fread($fp,$buffer);     echo $file_con;    }
    fclose($fp);}
function sendfile( $fullPath ){    $fsize = filesize($fullPath);    header("Pragma: public");    header("Expires: 0");    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");    header("Cache-Control: private",false);    header("Content-Type: application/pdf");    header('Access-Control-Allow-Origin:*');    Header("Accept-Ranges: bytes");    header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );    header("Content-Transfer-Encoding: binary");    header("Content-Length: ".$fsize);    ob_clean();    flush();    readfile( $fullPath );}

感謝 參考來源

2018-05-21 更新

JAVA實現

後面又用java開發了web版本,也貼下程式碼。

1.java服務端 這裡我是直接寫在servlet,其他需要自己建立 response 

直接從雲伺服器獲取資料,輸出給前端

response.setContentType("application/pdf");
ServletOutputStream sos = response.getOutputStream();
					
String destUrl="http://osq69h8nn.bkt.clouddn.com/BB8B.pdf";
URL url = new URL(destUrl);
HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
//連線指定的網路資源
httpUrl.connect();
//獲取網路輸入流
BufferedInputStream bis = new BufferedInputStream(httpUrl.getInputStream());
int b;
while((b = bis.read())!=-1) {
	sos.write(b);
}
sos.close();
bis.close();
return;

如果是讀取伺服器檔案,可以改為讀取檔案方式(我的做法是讀取WEB-INF下的PDF檔案,微笑)

InputStream is = new FileInputStream(path);

2.viewer.html 新增,務必放在 引用viewer.js前面 或者直接寫到viewer.js前面

<script>
	//獲取資料流
	var PDFData = ""; //定義一個空變數  
	$.ajax({  
	    type: "get", //如果報405錯誤就把post改成get  
	    async: false,  
	    mimeType: 'text/plain; charset=x-user-defined',  
	    url: "../../article.do?type=getPdf", //請求伺服器資料 
	    success: function(data) {  
		        PDFData = data; //data就是byte[]陣列,下面有介紹  
	    }  
	});  
	var rawLength = PDFData.length;  
	//轉換成pdf.js能直接解析的Uint8Array型別,見pdf.js-4068    
	var array = new Uint8Array(new ArrayBuffer(rawLength));  
	for (var i = 0;i < rawLength; i++) {  
		 array[i] = PDFData.charCodeAt(i) & 0xff;  
	}  
	var pdf_url = array;  
	//-----------
	 
</script>

3.viewer.js 修改

var DEFAULT_URL = pdf_url;
唯一要注意的就是 js請求方法的呼叫

相關推薦

PDF.js 2使用方式使用

前言因為工作需要,開發移動端線上閱讀PDF文件。所以找到了PDF.js,但PDF檔案是儲存在另外獨立伺服器,所以常規使用PDF.js會存在問題,經過搜尋查詢,實踐解決了問題。這邊提供嘗試過的2種有效方法1.繪製頁面html <div> <h1>

方式實現請求

防範 erro create ati brush col html5新特性 ole als 瀏覽器的同源策略 ? 提到跨域不能不先說一下”同源策略”。 ? 何為同源?只有當協議、端口、和域名都相同的頁面,則兩個頁面具有相同的源。只要網站的 協議名protocol、 主

springboot動態配置定時任務2方式整合Quartz多執行緒併發執行多個定時任務配置

我的專案是採用的idea+gradle+springboot專案構建,下面是springboot實現定時任務所需要的jar包 //定時任務使用 compile group: 'org.quartz-scheduler', name: 'quartz', version:

JS中的八常用的方式及其具體示例的總結(最新、最完整、最詳細)

JS中的八種常用的跨域方式及其具體示例的總結   這裡說的js跨域是指通過js在不同的域之間進行資料傳輸或通訊,比如用ajax向一個不同的域請求資料,或者通過js獲取頁面中不同域的框架中(iframe)的資料。   跨域問題是由於javascrip

js中幾實用的方法原理詳解

自身 標簽 cdc 返回 屬性和方法 插入 實用 封裝 判斷 這裏說的js跨域是指通過js在不同的域之間進行數據傳輸或通信,比如用ajax向一個不同的域請求數據,或者通過js獲取頁面中不同域的框架中(iframe)的數據。只要協議、域名、端口有任何一個不同, 都被當作是不同

jquery函數的2方式定義擴展extend函數調用

函數 col TE ont 方式 bsp style -- nbsp 事件函數的2種方式 1 $.each(obj,function () { });2 $("").each(function () { }) <

JS 中幾實用的方法原理詳解

這裡說的js跨域是指通過js在不同的域之間進行資料傳輸或通訊,比如用ajax向一個不同的域請求資料,或者通過js獲取頁面中不同域的框架中(iframe)的資料。只要協議、域名、埠有任何一個不同,都被當作是不同的域。 下表給出了相對http://store.company.com/dir/page

非同步請求訪問報錯問題 POST提交方式變成OPTIONS

跨域訪問報錯:無訪問許可權、POST請求過來變成OPTIONS 在返回servletResponse物件裡增加如下設定: servletResponse.setHeader("Access-Contro

JS問題以及採用JSONP方式解決問題

在做專案的時候,客戶要做成客戶端和服務端兩部分,客戶端向服務端進行認證,我開始的時候沒有直接替換ip地址,後來採用ip地址替換之後,出現了問題,後臺可以收到訪問的請求,但是無法拿到後臺返回的資訊,後來

【JavaScript】JS獲取子節點、父節點和兄弟節點的幾方式附CSS組合選擇器

【一】、JS獲取子節點的方式     1,通過獲取dom方式直接獲取子節點        1) document.getElementById("ID");        2) document.getElementsByTagName("tagName")        

JS開啟新視窗的2方式

1.超連結<a href="http://blog.csdn.net/qq_35624642" title="QC班長">Welcome</a> 等效於js程式碼 window.location.href="http://blog.csdn.net/qq_35624642"; 

react-pdf-js前端處理PDF的一方式

react-pdf-js前端處理PDF的一種方式 import React from 'react'; import PDF from 'react-pdf-js'; class MyPdfViewer extends React.Component { st

JS中事件繫結的2方式

    首先,在body裡寫一些內容。                    &nbs

js 實現純前端將資料匯出excel兩方式親測有效

由於專案需要,需要在不呼叫後臺介面的情況下,將json資料匯出到excel表格,參考了好多資料以及很多大佬寫的部落格終於實現,相容chrome沒問題,其他還沒有測試過,這邊介紹兩種實現方式,並附上程式碼和gif動圖,博主不才還望輕噴方法一將table標籤,包括tr、td等對j

利用maven建立hibernate專案實現類生成表的2方式+集合對映

1,利用配置檔案類生成表1)先建一個類,get和set方法@Data public class Salary { private Integer workcode; private St

將輸入框下拉列表radio的資料傳遞到後臺的2方式

#1 jqueryAjax的方式 通過jqueryAjax的方式將資料傳遞到後臺,這種方式適用於前臺的資料容易使用jquery獲取js獲取、資料較少的情況下。 具體方式: #a,在“提交”的button上加一個onclick事件,該事件執行一個js方法 #b,在js方法內寫

css實現寬高動態變化生成正方形div的2方式

在一些特殊的情況中,我們需要實現div隨著頁面放大縮小。 最近我遇到的一些問題就是在電腦上設計的時候,寫死的寬高在瀏覽器上顯示的時候一切正常,但是公司的60寸顯示器上卻是發生很大的變化,這都是解析度的不同造成的影響。 這種一般的情況可以根據按照百分比來設定寬

JS呼叫之JSONP--動態Script標籤方式實現

動態Script標籤的方式往往是用來訪問不在同一個域的伺服器內部的資料的。例如, 當前我的域名:d1.wwwcomy.com我需要訪問的資料:百度翻譯"chair"的結果由於百度翻譯和我的域名不在一個域名下,所以這個資料通過常規方式是沒辦法獲取的,是被瀏覽器的安全機制所禁止

使用js控制表單重複提交(1加鎖2事件方式3 EasyUI中解決表單重複提交)

方法一、var flag = true; $(function() { $("#interested").click(function() { beInterested(); }); }); function beInterested() { //$("#inte

React Native之使用“Debug JS Remote”時出現白屏問題

啟用“Debug JS Remote”出現白屏,主要原因就是瀏覽器跨域限制,從而導致不能通過瀏覽器進行web除錯的目的。 解決方