![](/img/trans.png)
[英]How to get URL from a browser(Chrome, Mozilla, Firefox…) while sharing highlighted text on react native app?
[英]Mozilla PDF - how to view PDFs from url in react app?
我遵循了一個關於如何使用 React 實現 Mozilla 的 PDF 查看器的快速教程。 我在這里做了一個密碼箱。 我想知道這是否可以通過導入 pdfjs 的節點模塊來實現。 因此,不要將包下載到公共文件夾中以將其與導入一起使用:
export default class PDFJs {
init = (source, element) => {
const iframe = document.createElement("iframe");
iframe.src = `/pdfjs-2.5.207-dist/web/viewer.html?file=${source}`;
iframe.width = "100%";
iframe.height = "100%";
element.appendChild(iframe);
};
}
此外,當 PDF 的源是 URL 時,這種設置不起作用。 如果我這樣做,我會收到一個錯誤:
PDF.js v2.5.207(內部版本:0974d6052)消息:文件來源與查看者的來源不匹配
我已經注釋掉了在pdfjs-2.5.207-dist/web/viewer.js 中檢查文件來源的代碼部分:
//if (origin !== viewerOrigin && protocol !== "blob:") {
// throw new Error("file origin does not match viewer's");
//}
但是,然后我得到了一個錯誤:
PDF.js v2.5.207(內部版本:0974d6052)消息:無法獲取
我怎樣才能解決這個問題? 是否可以將這個包像模塊一樣導入到 react 組件中,我如何將它用於帶有 URL 的外部資源的 PDF?
pdf 應位於同一主機上(包括相同的協議)。 將 pdf 托管在與您的應用程序/網站相同的 url 上,應該可以解決這個問題。
允許將 pdf 加載到其他頁面可能會導致各種安全風險。
如果您想在自己的主頁上顯示外部 pdf 的最新版本,基本上有兩種選擇。
在您的服務器上托管 PDF
運行服務器腳本 (cron),該腳本下載 pdf 並將其托管在您自己的服務器上。
允許跨域
如果您有權訪問托管 pdf 的服務器,您可以發送標題以允許跨域。
Access-Control-Allow-Origin: *
這方面的文檔真的很糟糕,但他們有一個存儲庫pdfjs-dist
和一些相關的文檔。
安裝
npm install pdfjs-dist
用法(來自DOC )
import * as pdfjsLib from 'pdfjs-dist';
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf';
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
// Asynchronous download of PDF
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var scale = 1.5;
var viewport = page.getViewport({scale: scale});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
服務工作者
您確實需要 service worker - 沒有它 pdfjs 就無法工作,所以 reactpdf 也不行。
如果您使用 CRA,並且不想使用 CDN,您可以執行以下步驟:
1)將worker復制到公用文件夾
cp ./node_modules/pdfjs-dist/build/pdf.worker.js public/scripts
2) 注冊 Service Worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `${process.env.PUBLIC_URL}/scripts/pdf.worker.js`
這是一個帶有 Mozilla 查看器和您的 pdf 的有效代碼和框。
注意事項:
混合內容:“https://codesandbox.io/”頁面已通過 HTTPS 加載,但請求了不安全的資源“http://www.africau.edu/images/default/sample.pdf”。 此請求已被阻止; 內容必須通過 HTTPS 提供。
Access-Control-Allow-Origin
,或者在同一來源,否則您會收到此錯誤:從源“https://lchyv.csb.app”訪問“https://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf”已被 CORS 政策阻止:否請求的資源上存在“Access-Control-Allow-Origin”標頭。 如果不透明響應滿足您的需求,請將請求的模式設置為“no-cors”以在禁用 CORS 的情況下獲取資源。
https://cors-anywhere.herokuapp.com/<URL_TO_PDF>
,它為您設置了Access-Control-Allow-Origin: *
,但不應在生產中使用! 所以總而言之,由於瀏覽器的限制,您的 pdf 沒有加載。 直接在您的應用程序中導入pdfjs
並從頭開始構建查看器(這是一項大量工作),並不能解決這些問題。
我對您的示例進行了更改,以便它接受一個 URL
我的代碼如下
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
const pdfjsLib = import("pdfjs-dist/build/pdf");
export default class PDFJs {
init = (source, element) => {
pdfjsLib.then((pdfjs) => {
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
var loadingTask = pdfjs.getDocument(`${source}`);
loadingTask.promise.then((pdf) => {
pdf.getPage(1).then((page) => {
var scale = 1.5;
var viewport = page.getViewport({ scale: scale });
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.height = viewport.height;
canvas.width = viewport.width;
element.appendChild(canvas);
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
});
});
};
}
你可以在這里看到結果
注意:正如其他人已經說過的,僅使用 react(或任何客戶端庫),在不解決 CORS 問題的情況下無法獲取外部資源(在您的情況下為 PDF)。 您將需要某種服務器端技術來解決它。 (除非您擁有/有權訪問外部資源服務器)
fetchPdf
上的請求並將文件本身作為響應返回
app.post('/fetchPdf', asyncMiddleware(async (req, res, next) => { const pdfPath = await downloadFile(req.body.url); if (pdfPath) { res.type('application/pdf'); res.sendFile(pdfPath); res.on('finish', function () { try { fs.unlinkSync(pdfPath); } catch (e) { console.error(e); console.log(`Unable to delete file ${pdfPath}`); } }); } else res.status(404).send('Not found'); })); function downloadFile(url) { return new Promise((resolve, reject) => { const absoluteFilePath = path.join(__dirname, `public/${crypto.randomBytes(20).toString('hex')}.pdf`); const file = fs.createWriteStream(absoluteFilePath); console.log(`Requested url ${url}`); const request = http.get(url, function (downloadResponse) { downloadResponse.pipe(file).on('finish', () => { resolve(absoluteFilePath); }); }).on('error', function (err) { fs.unlink(absoluteFilePath); resolve(null); }); }); }
注意:出於教育和學習目的,這會起作用,但是以這種方式將代碼部署到生產環境存在各種安全問題。
首先,您的服務器應該能夠向 Internet 上的任何站點發出請求
其次,如果沒有某種身份驗證,您的站點將成為任何希望下載被 CORS 阻止的外部資源的人的熱點(類似於 [https://cors-anywhere.herokuapp.com])
至於你的第二個問題,是的,可以將 pdfjs 庫與 react & npm 一起使用。
您可以參考yurydelendik 的repo,取自官方pdf.js mozilla 存儲庫。
我還在此處創建了一個相同的分支,演示了上述服務器端解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.