React 項目使用 pdf.js 及 Elasticpdf 教程

摘要:本文章介紹如何在 React 中使用 pdf.js 及基于 pdf.js 的批注開發包 Elasticpdf。簡單 5 步可完成集成部署,包括數據的云端同步,示例代碼完善且簡單,文末有集成代碼分享。
快照.png

1. 工具庫介紹與 Demo

1.1 代碼包結構

ElasticPDF基于開源 pdf.js (Demo地址:https://mozilla.github.io/pdf.js/web/viewer.html),增加了多種開箱即用的 PDF 批注功能。代碼包延續了 pdf.js-dist 獨立且完全離線的結構風格,僅增加了用于支持批注的離線 Javascript 代碼,與 pdf.js-dist 一樣可以快速完美集成到任何可以運行Javascript, HTML, CSS 的項目環境中,在公網及內網環境下運行。
項目結構-中文.png

1.2 Elasticpdf 在線 Demo

根據不同的功能及預算需求,有兩個版本的產品可供選擇,兩者僅在最終的批注保存階段有區別,產品 Demo 地址如下:

① 批注合成版: https://demos.libertynlp.com/#/pdfjs-annotation

② 專業批注版: https://www.elasticpdf.com/demo

2. 移動至 React 項目

移動 pdf.js 或 Elasticpdf 代碼包到 React 項目的 public 文件夾下。
package-position.png

pdf.js 成功導入 React 快照
pdfjs-快照.png

3. 導入 viewer.html

① 通過 <iframe> 導入 elasticpdf 或 pdf.js 代碼包中的 viewer.html 文件,注意路徑不要寫錯。

<!-- elasticpdf 示例 -->
<iframe id='elasticpdf-iframe' onLoad={initialPDFEditor} src='elasticpdf/web/viewer.html' style={{width:"100%",border:0,height:"700px"}}></iframe><!-- pdf.js 示例 -->
<iframe id='elasticpdf-iframe' onLoad={initialPDFEditor} src='pdfjs-3.2/web/viewer.html' style={{width:"100%",border:0,height:"700px"}}></iframe>

② 將 web 文件夾下 viewer.jsdefaultUrl 默認值置空,否則在第 ① 步中導入 viewer.html 時會默認加載 compressed.tracemonkey-pldi-09.pdf 文件,影響自定義加載文件的流程。Elasticpdf 代碼包中的 viewer.js 已默認修改完成。

// 原 defaultUrl 默認值
defaultOptions.defaultUrl = {value: "compressed.tracemonkey-pldi-09.pdf",kind: OptionKind.VIEWER
};// 置空后默認值
defaultOptions.defaultUrl = {value: "",kind: OptionKind.VIEWER
};

③ 在 React 頁面中的 <iframe> onLoad() 函數下調用 initialApp() 函數,由于 pdf.js 和 elasticpdf 中的函數都是在 iframe 的作用域下,因此必須在 iframe load結束后再初始化,否則無法獲取 iframe 的contentWindow,也就無法調用其中的函數。

var elasticpdf_viewer = null;
function initialPDFEditor() {listenPDFEditorMessage();elasticpdf_viewer = document.getElementById('elasticpdf-iframe').contentWindow;console.log('elasticpdf_viewer', elasticpdf_viewer);var pdf_url="compressed.tracemonkey-pldi-09.pdf";elasticpdf_viewer.initialApp({'language': 'zh-cn', // 交互語言'pdf_url': pdf_url,'member_info': { //用戶信息'id': 'elasticpdf_id','name': 'elasticpdf',},});
}// 監聽 pdf 編輯等各種信息的回調
function listenPDFEditorMessage() {window.addEventListener('message', (e) => {if (e.data.source !== 'elasticpdf') {return;}// pdf 加載結束的回調,可以在此處導入服務器上儲存的批注文件if (e.data.function_name === 'pdfLoaded') {console.log('PDF加載成功');reloadData();}});
}

④ pdf.js 初始化函數如下,主要內容為調用 PDFViewerApplication.open() 打開傳入的文檔鏈接,并使用 loadPdf() 函數監聽文檔是否初始化結束,最后通過 postMessage 廣播加載狀態至 React 頁面。

<script type='text/javascript'>//初始化函數function initialApp(paras) {var oriUrl=paras['pdf_url'];PDFViewerApplication.open(oriUrl);interval = setInterval('loadPdf()', 1000);}//監聽文檔是否初始化完成var interval = null;function loadPdf() {if (PDFViewerApplication.pdfDocument == null) {console.info('Loading...');} else {//文檔初始化完成console.log('PDF Load successfully');clearInterval(interval);//廣播信息postPDFData("pdfLoaded", '');}}//廣播 pdf.js 操作狀態信息function postPDFData(function_name,new_content){window.parent.postMessage({"type":0,"source":"elasticpdf",'function_name':function_name,"content":new_content},'*');window.postMessage({"type":0,"source":"elasticpdf",'function_name':function_name,"content":new_content},'*');}
</script>

⑤ 需要注意的是 pdf.js 端和存放 pdf 文件的都要支持跨域,否則會報 CORS 跨域錯誤。具體來說如果服務器是通過 Java 或者 Python 等程序提供文檔,則需要在程序中允許跨域;而如果是 nginx 服務器,則在配置中可以如下設置。

location / {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers *;add_header Access-Control-Expose-Headers  Accept-Ranges,Content-Range;add_header Accept-Ranges bytes;
}

對于 pdf.js 端的跨域,需要在 elasticpdf 或 pdf.js 的 viewer.js 中搜索 HOSTED_VIEWER_ORIGINS 并加入域名。

const HOSTED_VIEWER_ORIGINS = ["null", "http://mozilla.github.io", "https://mozilla.github.io"];

4. 導出 pdf 及批注數據

Elasticpdf 所生成批注數據的保存有兩種方式,我們推薦方式二。pdf.js 默認將批注寫入文檔,無法分離保存。

4.1 方式一:批注寫入PDF

將批注寫入到 pdf 中然后下載整個文檔,一般用戶可以通過Ctrl+S快捷鍵和 UI 按鈕來完成,這種方式完全不需要后端服務的支持。

在需要保存批注后 pdf 至服務器的場景中,可以通過如下代碼實現。

// 綁定該函數至 dom 用于觸發 pdf 保存
function getPDFData() {elasticpdf_viewer.getPDFData();
}// 接收pdf數據并且上傳至服務器
window.addEventListener('message', (e) => {if (e.data.source != 'elasticpdf') {return;}// 接收pdf數據if (e.data.function_name == 'downloadPDF') {let file_name = e.data.content['file_name'];let pdf_blob = e.data.content['pdf_blob'];let pdf_base64 = e.data.content['pdf_base64'];// 接收到 pdf 數據,其中 pdf_base64 字符串數據可以快捷上傳到服務器postService('upload-pdf-data', {'file_name':file_name,'file_id':'123ddasfsdffads','file_data':pdf_base64,});}
});

4.1 方式二:批注單獨保存

針對云端同步批注的需求,單獨將批注文件導出為JSON文件,傳輸并保存于服務器,之后加載回顯后可繼續編輯批注。

這樣的方式僅需一個在線PDF原文件,只傳輸很小體積的批注(通常不到 1M 大小),可以節約很多的存儲和寬帶費用。

// 在 pdf 批注編輯后的回調函數中可以讀取所有批注文件并且上傳至服務器
window.addEventListener('message', (e) => {if (e.data.source != 'elasticpdf') {return;}// pdf 批注編輯回調,可以在此處導出批注并傳輸到服務器if (e.data.function_name == 'annotationsModified') {// 僅獲取 pdf 批注文件,不寫入到 pdf 中let this_data = elasticpdf_viewer.pdfAnnotation.outputAnnotations();let annotation_content = JSON.stringify(this_data['file_annotation']);let file_name = this_data['file_name'];postService('upload-annotation-data', {'file_name':file_name,'file_id':'123ddasfsdffads','file_annotation':annotation_content,});}
});

5. 重載 pdf 及批注數據

單獨將 pdf 批注保存至服務器后,可以在加載 pdf 文件后再次從服務器中下載批注并且重載回顯到 pdf 上繼續編輯。

// 在 pdf 加載完成后的回調中可以從服務器請求相應的批注并重載于 pdf 上。
window.addEventListener('message', (e) => {if (e.data.source != 'elasticpdf') {return;}// pdf 加載完成的回調,可以在此處導入服務器上儲存的批注文件if (e.data.function_name == 'pdfLoaded') {let file_name = 'tutorial.pdf'let annotation_content =await postService('get-annotation-data', {'file_name':'tutorial.pdf','file_id':'123ddasfsdffads',});// 批注重載回顯于當前文件elasticpdf_viewer.setPureFileAnnotation({'file_annotation': annotation_content});}
});

以上的所有與服務器的交互需要前后端協同,后端服務器需要響應程序來接收和保存數據,對于 Elasticpdf 的用戶我們有簡單的 PHP、Python 及 Java 代碼示例供參考。

前端發起請求的示例函數 postService() 代碼如下。


// 與后端服務器進行網絡通信的函數
async function postService(url, data) {var new_data = new URLSearchParams();var encrpte_data = data;new_data.append('data', encrpte_data);var base_url = "your-server-url";var posturl = base_url + url;const response = await fetch(posturl, {method: 'POST',headers: {},body: new_data, });const resp = await response.json();resp['data'] = JSON.parse(resp['data']);return resp;
}

總結

至此,pdf.js 及 elasticpdf 集成于 React 項目的代碼完畢,帶有 pdf.js 代碼包的 React 示例項目包內容已上傳至 Github(網址:https://github.com/ElasticPDF/React-use-pdf.js-elasticpdf),可以直接下載。Elasticpdf 客戶如有其他應用場景需求歡迎聯系我們,我們將為您提供示例代碼。

溫馨提示:本文首發于?https://www.elasticpdf.com?,轉載請注明出處:https://www.elasticpdf.com/blog/react-use-pdfjs-and-elasticpdf-tutorial-zh.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900202.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900202.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900202.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python爬蟲:小程序逆向(需要的工具前期準備)

前置知識點 1. wxapkg文件 如何查看小程序包文件 打開wechat的設置&#xff1a; .wxapkg概述 .wxapkg是小程序的包文件格式&#xff0c;且其具有獨特的結構和加密方式。它不僅包含了小程序的源代碼&#xff0c;還包括了圖像和其他資源文件&#xff0c;這些內容在普通的文件…

Prolog語言的強化學習

Prolog語言的強化學習 引言 強化學習&#xff08;Reinforcement Learning, RL&#xff09;是機器學習的一個重要分支&#xff0c;它通過與環境交互來學習最優策略&#xff0c;以最大化累積獎勵。在強化學習中&#xff0c;智能體&#xff08;Agent&#xff09;通過試錯方式與環…

開源且完全沒有審核限制的大型語言模型的概述

開源且完全沒有審核限制的大型語言模型的概述 關鍵要點 研究表明&#xff0c;存在多個開源的大型語言模型&#xff08;LLM&#xff09;完全沒有審核限制&#xff0c;適合開放對話。包括基于 Llama、Mixtral、Phi-2 和 StableLM 的模型&#xff0c;參數范圍從 2.78 億到 4050 億…

思二勛:未來所有的業務都將生于AI、長于AI、成于AI

每個時代都有其標志性的技術&#xff0c;每個技術的產生或極大地解放了個體的勞動力&#xff0c;提高了個體與組織之間的協作效率&#xff0c;或極大地促進了生產效率或使用體驗&#xff0c;或將極大地優化了資源配置和供需匹配效率&#xff0c;從而提高人們的生活水平。從青銅…

瑪卡巴卡的k8s知識點問答題(六)

21. 什么是 ReplicaSet&#xff0c;說明它的主要用途。 ReplicaSet是k8s中的一個控制器&#xff0c;他用于保證任何時候&#xff0c;都有指定數量的Pod副本在運行&#xff0c;他是RC的升級版&#xff0c;支持更靈活的Pod選擇器&#xff08;基于集合的標簽選擇&#xff09; 主…

P7453 [THUSC 2017] 大魔法師 Solution

Description 給定序列 a ( a 1 , a 2 , ? , a n ) a(a_1,a_2,\cdots,a_n) a(a1?,a2?,?,an?)&#xff0c; b ( b 1 , b 2 , ? , b n ) b(b_1,b_2,\cdots,b_n) b(b1?,b2?,?,bn?) 和 c ( c 1 , c 2 , ? , c n ) c(c_1,c_2,\cdots,c_n) c(c1?,c2?,?,cn?)&…

免費送源碼:Java+ssm+MySQL SpringBoot社區配送服務系統小程序 計算機畢業設計原創定制

摘要 隨著科學技術的飛速發展&#xff0c;社會的方方面面、各行各業都在努力與現代的先進技術接軌&#xff0c;通過科技手段來提高自身的優勢&#xff0c;社區當然也不例外。社區配送服務系統小程序是以實際運用為開發背景&#xff0c;運用軟件工程原理和開發方法&#xff0c;…

SQL語句(一)—— DDL

目錄 一、SQL 基礎知識 &#xff08;一&#xff09;SQL 通用語法 &#xff08;二&#xff09;SQL 分類 二、DDL —— 數據庫操作 1、查詢所有數據庫 2、查詢當前數據庫 3、創建數據庫 4、刪除數據庫 5、切換數據庫 三、DDL —— 表操作 &#xff08;一&#xff09;查…

【Android】界面布局-線性布局LinearLayout-例子

線性布局&#xff08;LinearLayout&#xff09;是一種重要的界面布局中&#xff0c;也是經常使用到的一種界面布局 ? 在線性布局中&#xff0c;所有的子元素都按照垂直或水平的順序在界面上排列 ?如果垂直排列&#xff0c;則每行僅包含一個界面元素 ?如果水平排列&…

leetcode數組-長度最小的子數組

題目 題目鏈接&#xff1a;https://leetcode.cn/problems/minimum-size-subarray-sum/ 給定一個含有 n個正整數的數組和一個正整數 target** 。** 找出該數組中滿足其總和大于等于target的長度最小的 子數組 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其長度**…

一周學會Pandas2 Python數據處理與分析-Jupyter Notebook安裝

鋒哥原創的Pandas2 Python數據處理與分析 視頻教程&#xff1a; 2025版 Pandas2 Python數據處理與分析 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili Jupyter (Project Jupyter | Home&#xff09;項目是一個非營利性開源項目&#xff0c;于2014年由IPython項目中誕生…

前端頁面鼠標移動監控(鼠標運動、鼠標監控)鼠標節流處理、throttle、限制觸發頻率(setTimeout、clearInterval)

文章目錄 使用lodashjs庫手動實現節流&#xff08;通過判斷之前設定的定時器setTimeout是否存在&#xff09; 使用lodashjs庫 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Com…

java流程控制04:if選擇結構

選擇結構 if單選擇結構 if雙選擇結構 if多選擇結構 嵌套的if結構 switch多選擇結構 if單選擇結構 我們很多時候需要去判斷一個東西是否可行&#xff0c;然后我們才去執行&#xff0c;這樣一個過程在程序中用if語句來表示 語法&#xff1a; if(布爾表達式){//如果布爾表達…

在uniapp中,video比普通的標簽層級高解決問題

<view style"position: relative;"><video style"position: absolute;z-index:-1"></video><view style"position: absolute;z-index:999"></view> </view> 上面代碼并沒有解決view的層級比video高的問題&…

基于R語言與MaxEnt的物種分布建模全流程解析:從算法優化到科研制圖實戰

隨著全球氣候變化與生物多樣性保護需求的加劇&#xff0c;物種分布模型&#xff08;Species Distribution Model, SDM&#xff09;已成為生態學、保護生物學研究的核心工具。MaxEnt模型憑借其?對小樣本數據的強適應性?和?環境變量非線性關系的解析能力?&#xff0c;成為SDM…

DPDI版本升級說明

Dispatch PDI v2.0.3版本升級說明 自Dispatch PDI社區版全新版本V2.0.0于2025 年3月25日發布以來&#xff0c;我們始終緊密關注用戶動態&#xff0c;并全力協助用戶線上完成從V0.0.4到V2.0.0的遷移工作。在短短一周內&#xff0c;我們成功助力約90%的用戶完成了遷移。在此期間…

大鉦資本押注儒拉瑪特全球業務,累計交付超2500條自動化生產線儒拉瑪特有望重整雄風,我以為它破產倒閉了,擔心很多非標兄弟們失業

1. 交易概況 時間與主體:大鉦資本于2025年4月1日正式宣布完成對儒拉瑪特自動化技術(蘇州)有限公司及其全球子公司和關聯企業的收購。交易通過大鉦資本旗下美元基金設立的儒拉瑪特(新加坡)公司作為控股主體進行,交易金額未披露。 收購范圍:包括儒拉瑪特亞太、歐洲、北美等…

LabVIEW 調用 Python 函數

此程序是 LabVIEW 調用 Python 函數實現雙精度數相加的典型示例。通過 LabVIEW 搭建交互框架&#xff0c;借助 “Open Python Session” 創建 Python 代碼運行環境&#xff0c;定位 Python 模塊路徑后調用 “Add” 函數&#xff0c;最終實現數據處理并關閉會話。整個流程展現了…

基于SpringBoot的“考研學習分享平臺”的設計與實現(源碼+數據庫+文檔+PPT)

基于SpringBoot的“考研學習分享平臺”的設計與實現&#xff08;源碼數據庫文檔PPT) 開發語言&#xff1a;Java 數據庫&#xff1a;MySQL 技術&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系統展示 系統總體功能結構圖 局部E-R圖 系統首頁界面 …

恒盾C#混淆加密衛士 - 混淆加密保護C#程序

對于大部分C#開發者來說&#xff0c;寫完代碼點個發布就完事兒了&#xff0c;但你可能不知道——用記事本都能扒開你編譯好的程序&#xff01;像dnSpy這類反編譯工具&#xff0c;分分鐘能把你的EXE/DLL變回原汁原味的源代碼&#xff0c;商業機密赤裸裸曝光不說&#xff0c;競爭…