亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

用JavaScript實(shí)現(xiàn)PDF在線預(yù)覽:從渲染內(nèi)核到Canvas的完整指南

用JavaScript實(shí)現(xiàn)PDF在線預(yù)覽:從渲染內(nèi)核到Canvas的完整指南 簡(jiǎn)介面向Web前端開發(fā)者的PDF在線預(yù)覽實(shí)踐資料以PDF.js為核心覆蓋從庫(kù)引入、文檔加載、Canvas渲染到多頁瀏覽、縮放控制、進(jìn)度提示、文本選擇等關(guān)鍵能力并涉及Web Worker后臺(tái)解析與性能優(yōu)化思路適合有一定JavaScript基礎(chǔ)的讀者快速上手瀏覽器內(nèi)PDF查看場(chǎng)景。壓縮包共402個(gè)文件、整體約3.06MB完整示例代碼與靜態(tài)資源均整理在內(nèi)包含可直接運(yùn)行的HTML演示頁、配套JavaScript腳本、CSS樣式以及SVG/PNG/GIF界面元素和支撐PDF字體映射的bcmap、properties文件其中bcmap與properties數(shù)量較多是PDF.js正確渲染字體所必需目錄層級(jí)規(guī)整便于逐項(xiàng)查閱。已有3142人學(xué)習(xí)下載。除基礎(chǔ)用法外還能了解分塊加載、服務(wù)端預(yù)解碼等進(jìn)階方案實(shí)際開發(fā)時(shí)可借助演示頁面快速驗(yàn)證API調(diào)用順序與Canvas渲染細(xì)節(jié)并根據(jù)業(yè)務(wù)需要調(diào)整導(dǎo)航、縮放與加載策略對(duì)從零構(gòu)建或改造在線PDF預(yù)覽功能均有直接參考價(jià)值。1. 在線看 PDF用 JavaScript 把文件渲染進(jìn)網(wǎng)頁用 JavaScript 實(shí)現(xiàn)在線查看 PDF 文件聽起來是個(gè)常規(guī)需求真正做起來坑不少。瀏覽器自帶的預(yù)覽在不同內(nèi)核下表現(xiàn)差異很大——有的不支持、有的樣式完全不受控制、有的直接白屏。這個(gè)項(xiàng)目做的事情是把 PDF 渲染收攏進(jìn)一套可控的前端方案里通過開源渲染內(nèi)核把 PDF 解析成 Canvas 像素輸出支持翻頁、縮放、旋轉(zhuǎn)、全屏等交互能直接嵌入管理后臺(tái)、文檔系統(tǒng)或移動(dòng)端 H5。適合誰一類是給后臺(tái)系統(tǒng)加在線預(yù)覽 PDF功能的開發(fā)者另一類是正在調(diào)研前端 PDF 渲染方案、想看清完整實(shí)現(xiàn)鏈路的技術(shù)選型者。讀完你能搞懂項(xiàng)目怎么跑、核心鏈路長(zhǎng)什么樣還能拿到一份真實(shí)業(yè)務(wù)里趟出來的踩坑清單。2. 技術(shù)選型與項(xiàng)目結(jié)構(gòu)渲染內(nèi)核加業(yè)務(wù)殼的兩層拆法2.1 為什么不自研解析器也別用瀏覽器原生預(yù)覽PDF 格式遠(yuǎn)看是個(gè)文檔近看是一套復(fù)雜的對(duì)象系統(tǒng)交叉引用表、對(duì)象流、字體子集、圖像壓縮、內(nèi)容流指令……想從零解析再渲染工程量不低于寫一個(gè)輕量級(jí)排版引擎。商業(yè)項(xiàng)目里做這種自研基本是給自己挖坑所以我拿到這個(gè)需求的第一反應(yīng)就是找現(xiàn)成的渲染內(nèi)核把所有精力花在業(yè)務(wù)交互上。業(yè)界成熟的做法是直接用開源的 PDF 渲染內(nèi)核它的標(biāo)準(zhǔn) API 覆蓋了解析、渲染、文本提取全鏈路而且持續(xù)在維護(hù)字體兼容性這是自研很難追上的。瀏覽器原生預(yù)覽是另一個(gè)極端。它確實(shí)零成本但不同內(nèi)核的表現(xiàn)差異很大有的直接把 PDF 當(dāng)作附件下載有的雖然能在新標(biāo)簽頁打開卻完全沒有交互控制能力你既拿不到渲染進(jìn)度也改不了工具欄樣式更是完全隨緣。對(duì)產(chǎn)品而言這種黑匣子式體驗(yàn)無法接受——你沒法告訴用戶上次保存的批注存在哪也沒法統(tǒng)計(jì)多少人翻到了第幾頁。換句話說原生預(yù)覽適合內(nèi)部快速看一眼文件不適合作為產(chǎn)品的正式功能交付。這個(gè)項(xiàng)目采用了兩層拆法底層是一個(gè)開源 PDF 渲染內(nèi)核負(fù)責(zé)把 PDF 字節(jié)流解析成頁面對(duì)象再繪制到 Canvas 上上層是一個(gè)業(yè)務(wù)殼負(fù)責(zé)工具欄、翻頁、縮放、懶加載這些交互邏輯。兩層之間只通過幾個(gè)簡(jiǎn)單函數(shù)通信好處是內(nèi)核升級(jí)不影響業(yè)務(wù)代碼業(yè)務(wù)加功能也不用去碰渲染邏輯。我拆過的多個(gè)前端項(xiàng)目里這種內(nèi)核與業(yè)務(wù)解耦的組織方式是最容易維護(hù)的。我整理過一個(gè)方案對(duì)比表方便你做決定方案渲染質(zhì)量交互可控性集成成本典型問題瀏覽器原生預(yù)覽高低最低各內(nèi)核行為不統(tǒng)一樣式不可控第三方預(yù)覽服務(wù) iframe中低中存在上傳隱私風(fēng)險(xiǎn)受服務(wù)商限制開源渲染內(nèi)核 Canvas高高較高需要處理 Worker、內(nèi)存、跨域結(jié)論很直接如果你的產(chǎn)品對(duì)交互有要求或者要嵌在自家后臺(tái)里統(tǒng)一體驗(yàn)第三檔是唯一合理的選擇。選型定下來之后剩下的問題就變成了怎么把內(nèi)核的能力包裝成好用的業(yè)務(wù)功能。2.2 整體架構(gòu)Worker 線程、Canvas 渲染層、業(yè)務(wù)交互層拿我拆過的這個(gè)項(xiàng)目來說架構(gòu)可以分成三層往下看。第一層是文檔解析層。PDF 解析是大計(jì)算量活如果跑在主線程上用戶會(huì)明顯感到頁面卡頓尤其是有幾十頁、每頁都是高清掃描圖的那種文件。因此項(xiàng)目把解析工作全部放進(jìn)了 Worker 線程主線程只拿到解析好的頁面對(duì)象和元數(shù)據(jù)翻頁時(shí)再按需向 Worker 請(qǐng)求數(shù)據(jù)。這樣做的直接收益是用戶拖動(dòng)滾動(dòng)條時(shí)主線程始終是空閑的界面不會(huì)出現(xiàn)假死狀態(tài)。這個(gè)設(shè)計(jì)是整個(gè)項(xiàng)目能流暢跑大文件的前提。第二層是渲染層。每個(gè) PDF 頁面最終通過 Canvas 繪制出來。渲染層維護(hù)一個(gè)頁面對(duì)象池記錄哪些頁面已經(jīng)渲染過、哪些還在渲染中、哪些因?yàn)殡x開視口需要釋放資源。這里有個(gè)細(xì)節(jié)Canvas 的寬高是按設(shè)備像素比換算過的而不是直接用 PDF 的邏輯尺寸否則在 Retina 屏幕上會(huì)明顯模糊。這個(gè)細(xì)節(jié)做不做體驗(yàn)差距是肉眼可辨的——做過的人再看標(biāo)準(zhǔn)屏?xí)X得怎么那么糊。第三層是交互層。工具欄的縮放、旋轉(zhuǎn)、翻頁按鈕都在這層它不直接操作內(nèi)核 API而是通過一個(gè)狀態(tài)對(duì)象當(dāng)前頁碼、當(dāng)前縮放比、旋轉(zhuǎn)角度下發(fā)指令渲染層根據(jù)狀態(tài)變化決定重繪哪些頁面。三層之間是單向依賴交互層 → 渲染層 → 解析層。反向調(diào)用是被禁止的這保證了內(nèi)核替換時(shí)只需要重寫解析層和渲染層的對(duì)接部分業(yè)務(wù)殼一行都不用動(dòng)。數(shù)據(jù)流大致是這樣的用戶點(diǎn)擊下一頁 → 交互層更新狀態(tài)對(duì)象 → 渲染層讀取新頁碼向解析層要頁面對(duì)象 → 解析層從 Worker 拉取數(shù)據(jù) → 渲染層繪制 Canvas → 交互層更新頁碼顯示。整個(gè)鏈路清晰出問題的時(shí)候順著鏈路一層層查比在一個(gè)巨型文件里找要快得多。維護(hù)這份依賴關(guān)系的時(shí)候記住一個(gè)原則狀態(tài)只往下傳事件只往上拋。2.3 目錄結(jié)構(gòu)逐層拆解項(xiàng)目解壓后第一眼看到的目錄是這樣的pdf-viewer/ ├── index.html # 應(yīng)用入口頁承載畫布和工具欄 ├── package.json # 依賴聲明與腳本命令 ├── vite.config.js # 構(gòu)建配置含 dev 代理和 worker 配置 ├── public/ │ └── pdf.worker.min.js # 渲染內(nèi)核的 Worker 文件必須靜態(tài)可訪問 ├── src/ │ ├── main.js # 入口邏輯掛載應(yīng)用、讀取 PDF 地址 │ ├── viewer.js # 業(yè)務(wù)殼狀態(tài)管理與工具欄綁定 │ ├── render.js # 渲染層頁面繪制、縮放、旋轉(zhuǎn) │ ├── lazyLoad.js # 懶加載觸發(fā)與頁面對(duì)象池管理 │ ├── toolbar.js # 工具欄 UI 與事件綁定 │ └── style.css # 布局樣式 └── samples/ └── demo.pdf # 本地測(cè)試用示例文件每個(gè)文件的職責(zé)很單一。main.js 負(fù)責(zé)啟動(dòng)它只做兩件事讀取 URL 里的 file 參數(shù)調(diào)用 openPdf然后把文檔句柄交給 viewer.js。viewer.js 是全局狀態(tài)的中樞所有頁面共享的當(dāng)前頁碼、縮放比例、旋轉(zhuǎn)角度都存在這里它同時(shí)也負(fù)責(zé)把工具欄的按鈕事件翻譯成狀態(tài)變更。render.js 是整條渲染鏈路的執(zhí)行者所有 Canvas 繪制邏輯都在里面。lazyLoad.js 管性能用 IntersectionObserver 決定什么時(shí)候渲染、什么時(shí)候釋放。toolbar.js 管交互按鈕的 HTML 結(jié)構(gòu)和點(diǎn)擊綁定都在這里。你如果只想改按鈕樣式動(dòng) toolbar.js 和 style.css 就夠了想改渲染清晰度去 render.js 里找 scale 相關(guān)邏輯想支持新的操作比如批注核心是給 viewer.js 加狀態(tài)字段然后在 render.js 里加繪制分支。這種狀態(tài)驅(qū)動(dòng)渲染的設(shè)計(jì)讓每個(gè)新功能都變成加狀態(tài) 畫一筆而不是推倒重來。這也是我推薦照著這個(gè)結(jié)構(gòu)做二次開發(fā)的原因——文件少邊界清晰新手看一遍源碼就知道該改哪里。2.4 核心依賴與配置項(xiàng)目依賴非??酥普嬲芷饋肀匦璧闹挥袃蓚€(gè)一個(gè)開源 PDF 渲染內(nèi)核庫(kù)提供 getDocument、getPage、render 等標(biāo)準(zhǔn) API一個(gè)構(gòu)建工具這里用的是 Vite。其余都是開發(fā)輔助。package.json 里核心部分大致是這樣{ name: pdf-viewer, version: 1.0.0, scripts: { dev: vite, build: vite build, preview: vite preview }, dependencies: { pdfjs-dist: latest }, devDependencies: { vite: latest } }這里說明一下package.json 里寫 latest 是為了不鎖版本實(shí)際項(xiàng)目里你應(yīng)該在 npm install 之后讓它落一個(gè)具體版本號(hào)。為什么強(qiáng)調(diào)鎖版本因?yàn)殇秩緝?nèi)核的主庫(kù)和 Worker 文件是配套發(fā)布的版本不一致會(huì)在運(yùn)行時(shí)直接報(bào)錯(cuò)而且它升級(jí)頻繁小版本之間行為可能變化不鎖版本等于把自己的線上功能交給別人的發(fā)版節(jié)奏決定。vite.config.js 里通常要做兩件事配 base 路徑部署在子目錄時(shí)需要配開發(fā)代理把 PDF 資源的請(qǐng)求轉(zhuǎn)發(fā)到測(cè)試文件服務(wù)器。生產(chǎn)環(huán)境的跨域問題則靠 Nginx 的同源部署或后端網(wǎng)關(guān)的 CORS 配置來解決。提示W(wǎng)orker 文件的處理是整個(gè)項(xiàng)目最容易翻車的點(diǎn)。把 node_modules 里對(duì)應(yīng)版本的 worker 文件復(fù)制到 public 目錄是常見做法但別忘了每次升級(jí)內(nèi)核后重新復(fù)制否則版本一 mismatch線上立刻白屏。3. 核心模塊拆解一個(gè) PDF 頁面從字節(jié)流到屏幕像素的完整鏈路3.1 文檔加載getDocument 與 Worker 線程整個(gè)項(xiàng)目的第一步是加載 PDF 文檔。渲染內(nèi)核提供的標(biāo)準(zhǔn)入口是 getDocument它接受一個(gè) URL、一個(gè) ArrayBuffer 或者一個(gè) Uint8Array。項(xiàng)目里用的是 URL 方式代碼長(zhǎng)這樣// src/main.js import * as pdfjsLib from pdfjs-dist; // 關(guān)鍵點(diǎn)Worker 路徑必須在任何 getDocument 調(diào)用之前設(shè)置 pdfjsLib.GlobalWorkerOptions.workerSrc /pdf.worker.min.js; export async function openPdf(sourceUrl) { const loadingTask pdfjsLib.getDocument({ url: sourceUrl, // 禁用自動(dòng)預(yù)取避免大文件把內(nèi)存撐爆 disableAutoFetch: true, // 控制預(yù)取頁數(shù)的分塊大小配合懶加載使用 rangeChunkSize: 65536, }); try { const pdf await loadingTask.promise; console.log(文檔加載成功共 ${pdf.numPages} 頁); return pdf; } catch (err) { console.error(PDF 加載失敗, err); throw err; } }這段代碼里有幾個(gè)值得展開說的點(diǎn)。第一workerSrc 必須是一個(gè)靜態(tài)可訪問的絕對(duì)或相對(duì)路徑瀏覽器會(huì)用這個(gè)路徑去創(chuàng)建 Worker 線程。如果路徑 404整個(gè)加載會(huì)在第一步就失敗而且報(bào)錯(cuò)信息比較抽象不熟悉的人容易在業(yè)務(wù)代碼里瞎找。第二getDocument 返回的是一個(gè) loadingTask 對(duì)象上面有 promise 屬性也有 cancel 方法用于中斷加載——如果用戶打開一個(gè)上百兆的 PDF 后立即關(guān)掉你應(yīng)該調(diào)用 cancel 而不是干等否則網(wǎng)絡(luò)連接和解析線程會(huì)一直占著資源。第三disableAutoFetch 和 rangeChunkSize 是一對(duì)組合前者讓內(nèi)核不要一口氣把整個(gè)文件拉下來后者控制在按需加載時(shí)每個(gè)范圍塊的大小。這個(gè)組合對(duì)網(wǎng)絡(luò)體驗(yàn)影響很大局域網(wǎng)內(nèi)可以調(diào)大塊大小減少請(qǐng)求次數(shù)公網(wǎng)弱網(wǎng)環(huán)境則應(yīng)該調(diào)小。參數(shù)說明參數(shù)默認(rèn)值作用什么時(shí)候該改url無PDF 地址或數(shù)據(jù)源必填disableAutoFetchfalse關(guān)閉整文件預(yù)取大文件場(chǎng)景設(shè)為 truerangeChunkSize內(nèi)核決定分塊拉取的單塊大小網(wǎng)絡(luò)差時(shí)調(diào)小局域網(wǎng)內(nèi)可調(diào)大password無加密 PDF 的密碼處理帶密碼的文檔時(shí)傳入加載完成后拿到的 pdf 對(duì)象就是整個(gè)文檔的句柄后面所有操作——取頁、取元數(shù)據(jù)、取大綱——都從它出發(fā)。這個(gè)對(duì)象本身不直接渲染任何東西只是數(shù)據(jù)入口理解這一點(diǎn)對(duì)后面排查性能問題有幫助。3.2 Canvas 頁面渲染像素級(jí)細(xì)節(jié)與清晰度控制拿到文檔句柄后下一步是把某一頁畫到 Canvas 上。這是整條鏈路里最核心的函數(shù)// src/render.js let currentScale 1.5; // 全局縮放基準(zhǔn)值1 100% export async function renderPage(pdf, pageNumber, canvas, rotation 0) { // 1. 從文檔句柄中取頁面對(duì)象 const page await pdf.getPage(pageNumber); // 2. 按縮放比和旋轉(zhuǎn)角度計(jì)算視口 const baseViewport page.getViewport({ scale: currentScale, rotation }); // 3. 考慮設(shè)備像素比讓 Canvas 物理尺寸匹配屏幕實(shí)際像素 const dpr window.devicePixelRatio || 1; const viewport { width: baseViewport.width * dpr, height: baseViewport.height * dpr, }; // 4. 設(shè)置 Canvas 尺寸并繪制 canvas.width viewport.width; canvas.height viewport.height; canvas.style.width ${baseViewport.width}px; canvas.style.height ${baseViewport.height}px; const ctx canvas.getContext(2d); ctx.setTransform(dpr, 0, 0, dpr, 0, 0); const renderTask page.render({ canvasContext: ctx, viewport: baseViewport, }); await renderTask.promise; return page; }這段代碼是整個(gè)項(xiàng)目里最容易被改壞的地方我拆開說。第一步 getPage 是異步的因?yàn)閮?nèi)核需要去 Worker 線程請(qǐng)求頁面的內(nèi)容流網(wǎng)絡(luò)慢的時(shí)候這一步可能會(huì)等一兩秒。第二步 getViewport 返回一個(gè)描述該頁面在屏幕上占多大區(qū)域的對(duì)象scale 參數(shù)直接決定渲染尺寸1 就是 100%2 就是 200%頁面變模糊還是變清晰全看它。第三步是高分屏適配的關(guān)鍵Canvas 的物理尺寸要按 devicePixelRatio 放大否則 Retina 屏上文字邊緣全是鋸齒看著像沒加載完。第四步的 setTransform 做了對(duì)應(yīng)縮放保證繪制坐標(biāo)不混亂——如果少了這一步繪制出來的內(nèi)容位置會(huì)整體偏移尤其在高分屏上會(huì)錯(cuò)位得離譜。有件事要特別提醒page.render 返回的 renderTask 可以在中途 cancel。用戶在快速翻頁時(shí)前幾頁可能還沒畫完就離開視口了此時(shí)應(yīng)該調(diào) cancel 并釋放這個(gè)頁面的資源而不是等它慢慢畫完。項(xiàng)目里對(duì)這個(gè)問題做了一個(gè)渲染任務(wù)表// src/render.js const renderTasks new Map(); // pageNumber - { task, page } export function cancelRendering(pageNumber) { const entry renderTasks.get(pageNumber); if (entry) { entry.task.cancel(); // 中斷繪制 entry.page.cleanup(); // 釋放頁面對(duì)象持有的資源 renderTasks.delete(pageNumber); } }這張表的意義在于它把正在渲染的頁面變成了可管理的集合而不是散落在各個(gè)回調(diào)里的匿名任務(wù)。排查問題的時(shí)候只要看這張表里有哪些 pageNumber就知道當(dāng)前哪些頁面還占著資源。這也是我建議所有用到 Canvas 渲染的組件都該有的基礎(chǔ)設(shè)施。3.3 翻頁與懶加載IntersectionObserver 的實(shí)戰(zhàn)用法PDF 和普通網(wǎng)頁不一樣頁面數(shù)量可能幾百頁一次性全渲染會(huì)把瀏覽器直接拖垮。項(xiàng)目里用的是近處渲染、遠(yuǎn)處釋放的策略核心實(shí)現(xiàn)基于 IntersectionObserver// src/lazyLoad.js export function setupLazyRender(container, getPdf, getCanvasFor) { const observer new IntersectionObserver((entries) { entries.forEach(async (entry) { if (entry.isIntersecting) { const pageNum Number(entry.target.dataset.pageNum); const canvas getCanvasFor(pageNum); // 只渲染還沒渲染過的頁面 if (!canvas.dataset.rendered) { await renderPage(getPdf(), pageNum, canvas); canvas.dataset.rendered true; } observer.unobserve(entry.target); // 渲染完就停止觀察 } }); }, { root: container, rootMargin: 200px 0px, // 提前 200px 預(yù)渲染減少滾動(dòng)空白等待 threshold: 0.1, }); // 把所有頁面容器都掛上觀察 const placeholders container.querySelectorAll(.pdf-page); placeholders.forEach((el) observer.observe(el)); }這套做法的核心思想是用占位換時(shí)間每個(gè) PDF 頁面在 DOM 里先放一個(gè)占位容器容器上有>// src/toolbar.js render.js 的協(xié)作邏輯 export function updateViewerState(change) { const state getViewerState(); if (change.scaleDelta) { // 支持 50% 到 300% 的縮放范圍 state.scale clamp(state.scale change.scaleDelta, 0.5, 3); } if (change.rotationDelta) { // 每次旋轉(zhuǎn) 90 度取模保證在 0/90/180/270 之間循環(huán) state.rotation (state.rotation change.rotationDelta 360) % 360; } // 重繪所有已渲染的可見頁面 const visiblePages getVisiblePageNumbers(); visiblePages.forEach(async (pageNum) { const canvas getCanvasFor(pageNum); const page await getPdf().getPage(pageNum); await renderPageWithState(page, canvas, state); }); } function clamp(value, min, max) { return Math.min(Math.max(value, min), max); }縮放這里有個(gè)體驗(yàn)細(xì)節(jié)渲染是異步的如果用戶連續(xù)點(diǎn)擊放大按鈕會(huì)觸發(fā)多次渲染前一次還沒結(jié)束后一次就來了。項(xiàng)目里用了一個(gè)渲染中計(jì)數(shù)器如果前一次還在進(jìn)行中后一次請(qǐng)求會(huì)強(qiáng)制 cancel 掉前一個(gè) renderTask保證最終效果是最后點(diǎn)擊的那次。這個(gè)永遠(yuǎn)以最后一次操作為準(zhǔn)的策略在頻繁交互場(chǎng)景下非常關(guān)鍵能避免頁面閃爍和內(nèi)存堆積。做交互開發(fā)的都知道連續(xù)點(diǎn)擊下的競(jìng)態(tài)問題是最容易翻車的點(diǎn)之一。旋轉(zhuǎn)的邏輯也不復(fù)雜每次旋轉(zhuǎn) 90 度重新計(jì)算 viewport 后 Canvas 的寬高會(huì)自動(dòng)變化。布局層需要監(jiān)聽這個(gè)變化來調(diào)整頁面容器的高度否則容器高度不變就會(huì)出現(xiàn)上下留白。項(xiàng)目里用 ResizeObserver 監(jiān)聽每個(gè) Canvas 容器的尺寸變化然后動(dòng)態(tài)設(shè)置外層元素高度這樣旋轉(zhuǎn)后頁面布局不會(huì)亂。如果你要支持連續(xù)旋轉(zhuǎn)記得用取模運(yùn)算把角度限定在 0/90/180/270 四個(gè)值里不然旋轉(zhuǎn)十幾次之后角度就累積成上千了。4. 跑起來從克隆到線上部署的完整操作4.1 環(huán)境準(zhǔn)備與依賴安裝這個(gè)項(xiàng)目跑起來的門檻不高你只需要滿足三個(gè)條件Node.js 版本別太老建議 18 及以上這是構(gòu)建工具的最低要求、一個(gè)包管理器npm、pnpm、yarn 都行、能聯(lián)網(wǎng)裝依賴。這是我通常會(huì)做的第一步檢查node -v npm -v輸出正常就直接裝依賴。在項(xiàng)目根目錄執(zhí)行npm install裝的過程如果出現(xiàn)網(wǎng)絡(luò)超時(shí)多半是 registry 的問題換成國(guó)內(nèi)鏡像再裝一次就行。等安裝完成有個(gè)容易被忽略的操作確認(rèn) Worker 文件是否已經(jīng)就位。檢查一下 public 目錄下有沒有 pdf.worker.min.js 這個(gè)文件沒有就手動(dòng)從 node_modules 里復(fù)制cp node_modules/pdfjs-dist/build/pdf.worker.min.js public/這一步?jīng)Q定你后面會(huì)不會(huì)白屏別跳過。Windows 用戶把命令換成 copy 即可效果一樣。還有個(gè)小建議裝完之后順手看一眼 node_modules/pdfjs-dist/package.json 里的版本號(hào)記住它后面排查 worker 版本不匹配時(shí)要靠這個(gè)對(duì)照。4.2 啟動(dòng)開發(fā)服務(wù)器一切就緒后執(zhí)行npm run devVite 會(huì)起一個(gè)本地開發(fā)服務(wù)器默認(rèn)端口 5173。瀏覽器打開控制臺(tái)提示的地址你會(huì)看到頁面框架和一個(gè)工具欄。如果 URL 沒帶 PDF 地址參數(shù)頁面會(huì)嘗試加載 samples/demo.pdf 作為示例文件所以第一次啟動(dòng)一定能看到內(nèi)容不用額外準(zhǔn)備。如果你手上有一個(gè)現(xiàn)成的 PDF 想測(cè)試可以通過 URL 參數(shù)指定http://localhost:5173/?file/samples/demo.pdfmain.js 里有一段邏輯會(huì)讀取 file 參數(shù)然后把它作為 getDocument 的輸入源。開發(fā)階段用這個(gè)方式換測(cè)試文件非常方便不用改代碼。如果端口被占用Vite 會(huì)自動(dòng)換一個(gè)端口并在終端提示直接用新地址即可也可以手動(dòng)指定端口npm run dev -- --port 8080。開發(fā)服務(wù)器默認(rèn)開了熱更新改工具欄按鈕的文字會(huì)即時(shí)刷新但改 render.js 里涉及 Worker 配置的部分可能需要手動(dòng)刷新一次因?yàn)?Worker 的初始化不太參與熱更新。這個(gè)區(qū)別知道就行別在熱更新不生效的時(shí)候浪費(fèi)時(shí)間反復(fù)改代碼。4.3 生產(chǎn)構(gòu)建與部署開發(fā)調(diào)試通過后構(gòu)建生產(chǎn)版本npm run build構(gòu)建產(chǎn)物會(huì)輸出到 dist 目錄。部署時(shí)有個(gè)關(guān)鍵點(diǎn)dist 里的 pdf.worker.min.js 必須和 index.html 在同一個(gè)靜態(tài)服務(wù)下且路徑匹配。如果你把應(yīng)用部署在子路徑下比如 /tools/pdf-viewer/需要同步修改 workerSrc 的路徑為相對(duì)子路徑的形式// vite.config.js 里配置 base同時(shí) workerSrc 也跟著變 pdfjsLib.GlobalWorkerOptions.workerSrc ${import.meta.env.BASE_URL}pdf.worker.min.js;這段代碼利用 Vite 注入的 BASE_URL 環(huán)境變量自動(dòng)拼接正確的資源路徑部署到任何子路徑都不用手改。Nginx 的典型配置長(zhǎng)這樣注意把 PDF 文件的請(qǐng)求和頁面請(qǐng)求指向正確的目錄server { listen 80; server_name example.com; root /var/www/pdf-viewer/dist; index index.html; location /pdf/ { proxy_pass http://pdf-file-server/; } }location /pdf/ 這段是把 PDF 文件的請(qǐng)求轉(zhuǎn)發(fā)到文件服務(wù)器同時(shí)不設(shè) CORS 限制因?yàn)闉g覽器端是跨域請(qǐng)求。如果你的 PDF 和頁面放在同一臺(tái)機(jī)器上直接把 location 指向本地文件目錄也行。部署完記得清一下瀏覽器緩存靜態(tài)資源頻繁迭代時(shí)最容易出現(xiàn)改了代碼線上還是舊的這種玄學(xué)問題。4.4 驗(yàn)證清單啟動(dòng)完成后我習(xí)慣按下面這份清單過一遍確認(rèn)核心功能都正常打開示例 PDF第一頁完整渲染文字邊緣清晰無鋸齒。點(diǎn)擊下一頁第二頁出現(xiàn)在視口中滾動(dòng)時(shí)預(yù)渲染的頁面沒有白屏。連續(xù)點(diǎn)擊放大到 200%頁面重繪無閃爍Canvas 沒有拉伸模糊。旋轉(zhuǎn) 90 度后頁面容器高度自適應(yīng)沒有巨大留白。打開一個(gè) 100 頁以上的 PDF快速滾動(dòng)整個(gè)文檔瀏覽器內(nèi)存沒有持續(xù)暴漲。無痕窗口打開同樣的 URL確認(rèn) Worker 文件加載成功Network 面板能看到 pdf.worker.min.js 返回 200。任何一項(xiàng)異常優(yōu)先去查是不是 Worker 路徑、跨域配置或者版本不匹配的問題這三者占了 80% 的故障原因。逐項(xiàng)排查的順序建議是先看 Network 請(qǐng)求是否全部 200再看控制臺(tái)有沒有報(bào)錯(cuò)關(guān)鍵字worker、CORS、version最后才去看業(yè)務(wù)代碼。注意驗(yàn)證時(shí)一定要開無痕窗口因?yàn)闉g覽器擴(kuò)展尤其是翻譯類、截圖類插件會(huì)干擾 Canvas 渲染和 Worker 通信容易誤判為項(xiàng)目 bug。這個(gè)教訓(xùn)我是在一次演示前十分鐘才深刻領(lǐng)會(huì)的。5. 避坑指南五條血淚經(jīng)驗(yàn)每一條都真實(shí)踩過5.1 白屏且控制臺(tái)報(bào) Worker 加載失敗現(xiàn)象頁面打開后一片空白控制臺(tái)提示無法加載 worker 文件或者直接報(bào) API version mismatch。原因十有八九是 workerSrc 路徑不對(duì)。我見過把 worker 文件放到 src 目錄下的也見過版本拷貝錯(cuò)的還有直接把 node_modules 里的路徑當(dāng)靜態(tài)資源引用的。這個(gè)文件必須通過靜態(tài)服務(wù)器以資源方式訪問不能走模塊導(dǎo)入——你把它當(dāng)模塊 import構(gòu)建工具也不知道該往哪放。解決檢查 public 目錄下有沒有 pdf.worker.min.js確認(rèn)它與主庫(kù)版本一致。然后打開瀏覽器 Network 面板搜 worker 文件名看實(shí)際請(qǐng)求 URL 返回 200 還是 404。返回 404 就修路徑返回 200 還報(bào)錯(cuò)就核對(duì)版本號(hào)。最快的驗(yàn)證方式是在瀏覽器地址欄直接訪問 worker 文件的 URL能顯示一坨壓縮 JS 代碼就說明路徑是對(duì)的。5.2 跨域報(bào)錯(cuò)導(dǎo)致 PDF 加載失敗現(xiàn)象本地開發(fā)一切正常部署到線上后getDocument 加載遠(yuǎn)程 PDF 時(shí)報(bào)跨域錯(cuò)誤控制臺(tái)顯示 CORS policy 相關(guān)報(bào)錯(cuò)。原因PDF 文件放在另一臺(tái)服務(wù)器比如專門的文件服務(wù)該服務(wù)器沒有返回 CORS 響應(yīng)頭。很多人以為 Worker 是后臺(tái)線程就可以繞過瀏覽器安全模型實(shí)際上 Worker 里發(fā)起的請(qǐng)求同樣受同源策略約束。解決兩個(gè)辦法。第一個(gè)是在文件服務(wù)器上配置 Access-Control-Allow-Origin: *內(nèi)網(wǎng)文件服務(wù)可以這么做公網(wǎng)要按業(yè)務(wù)收緊。第二個(gè)是讓前端先 fetch 該文件拿到 ArrayBuffer再交給 getDocument。第二種繞開了跨域限制但會(huì)多占一份內(nèi)存超大文件不推薦。項(xiàng)目里默認(rèn)用第一種配合 Nginx 配置最省事。如果兩種都不行檢查一下是不是部署時(shí)把 PDF 請(qǐng)求代理到了錯(cuò)誤的后端地址。5.3 大 PDF 頁面渲染卡頓滾動(dòng)像幻燈片現(xiàn)象打開一個(gè) 50MB、每頁都是高清圖片的 PDF快速滾動(dòng)時(shí)頁面明顯卡頓甚至瀏覽器長(zhǎng)時(shí)間無響應(yīng)。原因頁面對(duì)象和 Canvas 紋理都沒有及時(shí)釋放。只做懶加載不做事后釋放內(nèi)存會(huì)隨著滾動(dòng)位置不斷膨脹最后觸發(fā)頻繁 GC一 GC 就卡。還有可能是 disableAutoFetch 沒開內(nèi)核在后臺(tái)把整個(gè)文件都預(yù)取了一遍流量和內(nèi)存一起浪費(fèi)。解決在渲染一個(gè)新頁面之前主動(dòng)回收所有離開視口很遠(yuǎn)的頁面。項(xiàng)目里維護(hù)了一張頁面使用時(shí)間表每次渲染標(biāo)記當(dāng)前時(shí)間戳定時(shí)檢查并調(diào)用 page.cleanup() 釋放超過閾值的頁面。同時(shí)確認(rèn) disableAutoFetch 已開啟讓內(nèi)核只加載臨近范圍的數(shù)據(jù)。如果單頁尺寸特別大還可以考慮把 Canvas 的分辨率上限設(shè)一個(gè)值超過就不按 dpr 放大犧牲一點(diǎn)清晰度換流暢度。5.4 文字渲染正常但部分符號(hào)和中文變成亂碼現(xiàn)象大部分 PDF 文字渲染正常但某些字符顯示成方塊或亂碼尤其在標(biāo)題和特殊符號(hào)上。原因PDF 內(nèi)嵌字體子集不完整字體的字符映射表在解析時(shí)出了問題。這種情況常見于從某些辦公軟件導(dǎo)出的 PDF字體被裁剪得只剩部分字形。另一個(gè)可能性是渲染內(nèi)核版本太老對(duì)某些字體格式支持不全。解決先升級(jí)渲染內(nèi)核到最新版本字體支持是持續(xù)修復(fù)的版本升級(jí)能解決大多數(shù)問題。如果還不行打開系統(tǒng)原生預(yù)覽對(duì)比測(cè)試原生也亂碼說明文件本身有問題只能讓業(yè)務(wù)方換導(dǎo)出方式原生正常而項(xiàng)目里亂碼重點(diǎn)排查內(nèi)核版本和 Worker 是否匹配再檢查 PDF 里嵌入的字體子集是不是被某些壓縮工具處理過。5.5 移動(dòng)端雙指縮放無響應(yīng)頁面滾動(dòng)沖突現(xiàn)象手機(jī)上打開預(yù)覽器雙指縮放頁面時(shí)觸發(fā)的是頁面滾動(dòng)而不是 PDF 縮放內(nèi)容也沒有完整適配屏幕。原因?yàn)g覽器的觸摸默認(rèn)行為把雙指手勢(shì)當(dāng)作滾動(dòng)Canvas 上繪制的內(nèi)容無法直接接收觸摸事件。移動(dòng)端沒有 hover 狀態(tài)工具欄的可點(diǎn)擊區(qū)域也變小了交互體驗(yàn)和桌面端完全不一樣不能用同一套邏輯硬扛。解決在 Canvas 容器上監(jiān)聽 touchstart / touchmove / touchend當(dāng)檢測(cè)到兩指觸屏?xí)r調(diào)用 preventDefault 阻止默認(rèn)滾動(dòng)并把兩指距離的變化換算成縮放比例交給縮放邏輯。同時(shí)給工具欄按鈕設(shè)置至少 44px 的最小觸控尺寸旋轉(zhuǎn)和全屏按鈕放到容易夠到的拇指區(qū)域。測(cè)移動(dòng)端用真機(jī)測(cè)別信模擬器模擬器里的觸摸事件和真機(jī)差異很大很多問題只有真機(jī)才能復(fù)現(xiàn)。6. 二次開發(fā)把這個(gè)預(yù)覽器改成你自己的 PDF 工具這套預(yù)覽器最值錢的地方不是能看 PDF而是它把渲染流程完全暴露給了你所有交互都能定制。我改造時(shí)最先做的是加一個(gè)下載按鈕讓預(yù)覽和下載在同一個(gè)工具欄里完成// 新增下載當(dāng)前文檔 function downloadPdf(pdfDoc, fileName) { pdfDoc.getData().then((data) { const blob new Blob([data], { type: application/pdf }); const link document.createElement(a); link.href URL.createObjectURL(blob); link.download fileName || document.pdf; link.click(); URL.revokeObjectURL(link.href); }); }再進(jìn)一步可以給頁面加上文本選擇能力。渲染內(nèi)核里其實(shí)已經(jīng)解析出了文本內(nèi)容通過 page.getTextContent() 可以拿到每頁的文字和坐標(biāo)信息把它們浮在 Canvas 上方做一個(gè)透明的文本層就能實(shí)現(xiàn)選中復(fù)制。這是做關(guān)鍵詞高亮、批注功能的基礎(chǔ)。我一般會(huì)把這個(gè)文本層的 z-index 設(shè)為 Canvas 之上pointer-events 設(shè)為 auto這樣鼠標(biāo)選中文字時(shí)不會(huì)影響到下面的畫布。性能方面還有一個(gè)值得做的優(yōu)化對(duì)經(jīng)常打開的大文件在關(guān)閉時(shí)強(qiáng)制調(diào)用銷毀邏輯而不是依賴瀏覽器 GC。我在項(xiàng)目里給 viewer 加了一個(gè) destroy 方法統(tǒng)一清理 Worker、頁面對(duì)象、Canvas 上下文和所有觀察器。從那以后我每次接手新的前端項(xiàng)目都會(huì)先問一句這個(gè)組件有沒有對(duì)應(yīng)的銷毀流程沒有的話第一個(gè)任務(wù)就是補(bǔ)上它。這個(gè)小習(xí)慣幫我避開了不知道多少內(nèi)存泄漏的隱形坑。改完這些你的預(yù)覽器就已經(jīng)不是看 PDF 的工具而是一個(gè)可以繼續(xù)往上加批注、加簽章、加文檔對(duì)比的基座了。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
男人的天堂啪啪啪啪啪蜜桃不卡| 黄片免费看黄片免费看| 乱伦a片视频| 中文字暮97| 婷婷五月天激情四射| 九九成人视频| 日本久久女同性恋视频| 蜜桃视频成a人v在线| 中文97国产| 天堂8在线新版官网| 色综合1991| 大香蕉五月天| 亚洲无线码欧洲精品区别| 伊人991| 乱人伦 国语对白:视频直接看| 欧美熟女逼久久久久久| 午夜精品久久久久久久99蜜桃一| 酒色综合网| 国产视频一区二区在线| 日本激情免费大片| 97视频在线播放| 老鸭窝成人| 色欧美天天| 郑州宾馆老熟女露脸啪啪| 无码精品啪啪啪一区二区三区三州| 99国内精品| 性在久久久久久| 亚洲黄色视频在线观看视频| 美女爽到高潮91| 久7色| 成人乱码一区二区三少妇| 精品美女少妇一区二区| 欧美成不卡网| 中文字幕第9页萱萱影音先锋| 熟女在线视频| 色姑娘综合网| 另类在线| 欧美日韩性爱无码| 玖色AV| 99自拍B亚洲 | 欧美色狠| 青青久久艹| 97超碰美国| h在线看免费版在线看| 国产强奸91| 日本中文熟女视频| 四季av一区二区凹凸精品小说| 中文字幕女同在线| 亚洲日韩久久精品一区| 大鸡吧尹人在线| 丁香久久| av72网| 久草电影网| 日产中文字幕2020| 久操九九九九| 97色欧州| 日本精品88888888| 99操逼| 久久女女| 亚洲人综合| 久热精品在线| 永久电影三级在线观看| 999综合网| 婷婷五月天激情四射| 97超碰人人模人人拍人人| 性爱Av免费| 国产色呦呦| 9 9精品一区二区三区| 中文字幕 av v| 67914亚洲精品| 综合网欧美在线| 熟女自慰久久久| 安微少妇操BBB| 亚洲天堂在线怕怕视频| 欧美性爱伊人| 一个人在线看的黄色电影网站| 国产美女激情| 亚洲成成熟女人综合一区二区| 超清中文乱码字幕| 激情欧美97| 亚洲阿v天堂无码z2018| 免费看污网站| 天天欧美97| 亚洲综合99999| 老司机老司机午夜影院| 亚洲第一无码播放立川理惠| 麻豆人妻精品一区二区| 老司机午夜精品福利视频一区二区| 嗯嗯啊中文字幕| 一区二区三区色综合| 国产精品久久久九九九| 亚欧操逼片在线观看| 热99re69精品8在线播放| 黑人猛交| 午夜大香蕉| 精品美女少妇一区二区三区| 国产一区二区三区视频在线看| 一本道综合色图| 久久九九精品一区二区| 日韩免费在线视频观看| 欧美永久激情一区二区| 色姑娘综合网| 99久久这里只有精品| 亚洲欧美国产精品久久久久久久| 亚洲男人天堂网站| 死我十八禁| 黄色片A级一区二区三区| 97香焦色区| 天天干1区2区在线| 天天综合网91| 九九av| 日韩综合色网| 四虎国产成人精品免费一女五男| 激情文学 国产一二三aV| 黄页网站成人免费| 亚洲一区中文字幕一区| 精品人妻1237| 久久精品国产精品一区 | 九九热在线视频| 亚洲精品蜜桃久久久| 日本成人电影资源网| 国产a级精品| 久湿久久| 边做饭边操逼逼| 色97国产69香蕉| 一区二区三区不卡视频| 99色在线| 精品久久久久综合无码| 国产不良强奸视频免费看| 国产成人亚洲精品无码古代早漏男| 精品人妻夜夜草| 国产精品4p在线观看| 狠插 制服 自拍| 三级色综合| 色哟哟-国产专区| 国产一区二区三区高清视频| 诱惑人妻欧美一区在线播放| 97在线观看播放视频| 麻豆影音天美视频| 国语国产操逼伊人AV网| 91精品老女人| 97精品全部| 中字乱伦AV| 又黄又爽在线观看视频| 婷婷操逼| 美女诱惑久久| 人妻一区久久二区三区色播| 日逼国产| 2017,超碰| 日本三级黄页| 人妻精品免费一二三区| 九九九热精品| av天天在线观看| 黄视频免费| 亚洲熟女乱色一区二区三区久久久 | 欧美日韩美女精品久草一区二区三区 | 久热久| 亚洲本色精品一区二区久久| 国产超碰欧美| 日韩影片中文字幕一区二区三区| 图片区小说区| a片亚洲一本通视频| 亚洲Av噜噜一区二区三区妖精| 日本精品网站在线中文| 9丨久久九九九| 亚州欧美总和| 九九久久一区二区三区| 亚洲黄色网址视频| 亚州一区二区成人片免费| 久久久久久久久久久精| 二级久久网| 色狠狠综合| 精品久久久久久AV无码| 亚洲人妻色图| 国内精品嫩模A∨私拍小视频| 凸凹视频在线观看| 极品国产内射| 四虎视频在线观看| 欧美亚洲日韩人妻在线观看| 十八禁的黄污污免费网站| 人妻天堂网| 日韩av色图| 东北女人av| 69精品久久久久中文字幕| 2024年最新色情网站在线观看| 99热国产精品| 亚洲女人毛茸茸91| 100啪啪视频大全| 美女让帅哥通她小鸡鸡| 天天综合网91入口| 天操天操夜操夜月操月年年操| 在免费jIzzjIzz在线视频| 一区二区三区美女超清| 亚洲无码电影久久久| 日韩欧美三级| 噜噜噜噜天天狠狠| 久久是精品| 久久日本熟妇熟色高清| 国产男女无套97| 久久色一区| 视频二区美腿丝袜制服人妻欧美| 99视频精品| 干少妇视频| julia国产在线 | 国产福利精品98视频| 日日骚网站| 欧美激情 亚洲色图| 丝袜高跟澳门91视频| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 黄骗免费网站| 岛国片在线播放| www.色吧5.com| 久久国产免费激情视频| 天天操天天干一区二区| 日韩不卡a级视频专区| 乱伦AVxx| 九月色婷婷| 在线观看一卡二卡| 嗯……啊…嗯嗯…啊…好舒服| 国产天天骚| 国产农村妇女精品一二区| 玖玖爱综合| 人妻社区男人天堂| 大香蕉色欲AV| 东京热毛片调教| 欧美综合色,www| 久久久精品网站| 91av一区二区在线观看| 亚洲av噜噜噜噜噜噜| 婷婷色色五月天福利| 亚洲在线网站| 日韩欧美一级特黄大片| 色999亚洲人成色| 97久久资源| 蜜桃精品视频一区| 亚州色综合| 国产精品黑人一区二区三区| 国产精品岛国片在线观看| 日本一级一级一级一级| 日本一二三高清| 国产成人精品午夜福利| 4虎在线观看| 欧美一级特黄淫片在线观看| www激情| 少妇毛片久久| 96精品久久久| 男插女青青影院| 思思性爱| 91麻豆天美国产| 男人天堂毛片| 欧美1区二区三区公司| 日韩免费看黄片| 国产天天骚| 蜜乳AV.COM| 黄网色一区二区三区四区精品| 五月婷婷激情网| 久久精9| 猛猛干| 黄骗免费| 亚洲精品欧洲精品| 在线视频 亚洲精品| 亚洲导航深夜福利| 综合97亚洲| 欧美黑人熟妇精品91| 园内精品自拍视频在线播放| 亚洲精品a人片在线观看视| 色淫网站优优视频| 夜夜国产一区| 香蕉综合网| 大香网站| 日韩精品三区四区| 国产路线专区| 亚洲AV成人无码一区二区三区在线观看| 9久综合网| 91伊人久久在线| 日韩精品午夜操呦呦不卡影院| 日韩精品 资源| 无卡一区=区| 啪啪啪东京| 成人性生活高清视频在线播放| 亚洲av综合色区图片亚洲| 久无码| 东京热,男人的天堂| 日韩精品一区二区日韩| 男插女青青影院| 秋霞色色影院| 乱人伦 国语对白:视频直接看| 成人九九| www.婷婷| 好涩综合| 蜜桃臀av在线观看| 国产精品一区二区三区免费视频| 无码高清少妇久久| 蜜桃视频精品一区二区三区| 国产精品一区二区a| 性爱视频免费网址| 亚洲男人的天堂AV| 97人妻免费中文字幕| 久久亚洲天天做| 国产亚洲精品A在线观看下载| 99999久久久久9国产精品| 大象AV在线| 熟女色图在线| 在线免费观看日韩一区| 久草草一二三四区久久| 五月丁香激情啪啪| 日韩欧美日韩| 中文久久一区| 日本一级婬片试看三分钟| 色妇91| 精品少妇一区二区三区在线视频| 高颜值美女口爆高潮浪叫| 九色视频91| 欧美性夜| 精品无人区麻豆乱码久久久| 精品一啪| 日本阿v天堂在线观看| 国内黄色精品| 日韩无码精品综合久久| jizzjizz欧美| 精品制服美女中文一区二区三区| 六月婷婷五月丁香| 性久久久| 久久一二三四五六七八九区| 婷婷五月天小说| 中文字幕人妻资源在线| 蜜臀在线网站| 丝袜综合| 色婷婷基地| 国产无码精品久久久久久| av麻豆啪啪| 婷婷色色五月| 深夜国产一区二区三区在线看| 玖玖资源视频一区二区三区| 免费看污网站| 亚洲天堂 视频你懂的| 神马久久久久久| 久久婷婷欧美| 婷婷在线视频| 在线观看国产黄色| 免费观看网黄| 性色aV一区二区三区噜噜| 色偷偷色偷偷欧美日韩| 99精品丰满人妻无| 99精品在线| 中文字幕一二三区| 久久久久国产精品喷潮免费观看臀| 综合网亚洲在线| 密臀AV在线| 2020中文字幕| 国产原创剧情在线丝袜| 亚洲小电影免费涩涩成人在线高清| 欧美色蜜桃97| 国产精品久久久久久夜夜夜夜| 日韩AV电影网站| 干婷婷综合网| 操高情无码| 免费福利视频中文字幕| 福利视频香蕉免费一区二区在线| 久久久久久人体| 天天色踪合| 强上我不卡卡| 超碰97资源中文字幕| 99综合网| 97人人色| 欧美色图 人妻| 精品人妻1237| 偷窥自拍亚洲色图| 操人妻少妇中文 | 国产亚洲禁久一区二区| 日韩人妻一二三区视频| 大屁股人妻女教师撅着屁股| 放黄片放3级黄片没穿衣服| 欧美亚洲在线| 九九九九精| 91色欧美| 欧美激情区| 精品少妇99| 天天操福利视频综合网站| 午夜一区二区三区国产| 殴美色网| 亚春色色| 欧美美女视频| 老妇女91| 免费精品国偷自产在线在线 | 亚洲古典另类欧美在线| 国产麻豆福利av在线播放| 久操凹凸视频| 8050午夜少妇无码| 无码伊人久久大杳蕉中文无码| 欧美日韩国产高清在线一二三区| wwwcaobibi| 日本在线视频导航| 91美女丝袜诱惑视频| 人妻久久久久久久久久久久久久久 | 色嗨嗨在线| 在线人人人人人人精品超 | 亚洲 欧美 小说| 日本二三四区| 96一区二区三区| 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | 亚洲高清内射| www.人人摸在线视频| 日本不卡在线二区三区| 18禁看网站一区| ,成人免费啪啪视频| 青青草视频这里只有精品| 国产精品无码av在线| 久久综合资源一区二区| 5278欧美一区二区三区| 五月婷婷性爱| 亚洲丝袜色图| 97操B| 精品一区二区三区免费古装毛片香港三级日本三级人妇 | 67194无码不卡| 日逼五月天| 色97国产69香蕉| 亚洲熟女精品| 999日韩中文精品观看视频。| 久久精品综合| 激情小说亚洲色图| 综合久久六月久久婷婷| 日韩精品 资源| 91中文精品日韩欧美在线| 国产97综合| 被窝影院午夜看片无码| 久久婷婷亚洲| 中文字幕第23区| 九九亚洲| 激情五月综合网| 天操老女人| 超碰99re| 色婷亚洲五月在线观看| 91夜夜蜜桃臀1区2区3区| 啊啊啊轻点在线观看| 中文字幕久久婷婷丁香五月天| 成人性爱高清视频免费看| 亚洲国产一区二区三区在线| 久9综合在线| 最近2018中文字幕在线高清第一页| 自拍大香蕉乱插| 人人污日韩一区二区| 蜜臀Av一区二区三区| 91东京热男人的天堂| 超碰久热| 99热一区二区三区四区| 日韩午夜精品一区二区三区电影| 操美女人妻| 国产精品诱惑| 色久综合| 亚洲人妻精品一区二区| 久9热| WWW美腿丝袜香蕉中文| 久久久久久97| 麻豆天美一区二区| 成人欧美日超碰| 18禁止看精品中文字幕| 男人的天堂 在线一区| 26uuu欧美| 色天堂在线观看| 欧美性爱18观看| 曰韩欧美国产传媒麻豆第一区| 后入综合久久| 免费一级毛片在线视频观看| 岛园激情| 一摸二插三插| 色综合网1| 亚洲成人在线资源| 欧美国产日韩高清在线| JuliaAnnXXX888| 青青操综合网| 中文字幕加勒比海高清无码免费视频| 久久一二三四五六七八九区| 亚洲高清无码AAA久久久精品| 97频视在线| 91在线超高颜值国产| 大奶尤物鲍汁淫荡欧美视频粉嫩夜夜骚 | 久久人妻无码毛片A片麻豆| 懂色av色欲av蜜臀av| 国产久久一区二区| 亚洲aV性爱| 久久老熟女| 一区二区偷拍拍视频| 大香蕉综合网| 日韩情色AV| 日本Xx性爱| 性感美女91影视| 亚洲有码 视频一区| 欧美色999| 亚洲自拍一区夜夜操| 日韩国产乱子伦App| 玖玖无码超碰| 开心六月色| 久久精品国产亚洲AV高清演员表| 蜜臀在线看片| 打av高清| 91天堂色男人的天堂| 97久久久网站| 日日夜夜模| 综合色播| 中国AV美女| 久久九九久精品国产尤物|国产精品爽黄69天堂A片潘金莲,国产亚洲精品第一综合 | 色综合久久夜色精品国产天堂 | 熟女一区二区| 日韩成人精品视频自拍| 福利视频网站| 九七毛片九九毛片| 中文高清一区二区的| 一级日本牲交大片好爽在线看| 拍拍拍拍大尺度黄色三级片拍拍拍拍拍照| 午夜免费视频1000| 国产一级不卡在线观看| 青青草中文字幕| 日本新免费二区三区| 午夜天堂精品久久久久91| 欧美一区二区福利在线| 色欧洲| 精品人妻一二三四区视频| 国产精品在线一区二区| 亚洲男人的天堂V| 日本道久久综合色色| 精品人妻中文字幕高清| 免费男人的天堂| 操b网站亚洲无码| 99∨VTV| 99久久精品无码一区二区| 97香蕉网| 国产精品噜噜噜日日日| 综合网亚洲1| 激情文学欧美| 熟妇高潮一区二区免费视频| 亚洲国产激情国产av| 久久久久久69国产一区二区| 夜夜嗨视频| 久久久亚洲熟妇资源| 操曰本熟女| 99久久综合| 看看小穴| 日韩三级久久久| 久操热| 偷看洗澡一二三区美女| 顶级丝袜熟女一区二区三区| 成年人三级黄色片视频| 伊人网青青| 亚洲图片欧洲图片aⅴ| 玖玖综合视频| 啊啊啊啊啊啊啊在线| 国产传媒1234区| 久久久久久久九九九九九九| 东京热激情视频一二三区| aaa一级黄片| 粉嫩不卡一区二区性爱| 日韩人成网站在线播放| 天天搞在线综合网| 性久久久| 久久久久久久9999| 亚洲在线91| 久操视频在线观看| 在线视频 亚洲精品| 亚洲AV无码乱码| 精品人妻中文字幕高清| 综合久久久久久久久91| 波多野结衣AV无码一区| 激情熟女12P| 澳门黄片一香蕉视频| 人人干黄色| 亚洲一级性爱视频免费看| 天天插夜夜操| 人人摸人人干人人拍97| 女人高潮大叫一级毛片| 色婷婷丁香五月天| 精品91摸| 啊啊啊啊操死我了| 日本高清一本二本免费不卡| 亚洲骚逼少妇| 色综合av综合久久| 国产美脚女优尤物在线观看| 无码欧美有限公司| 美女AV一区二区| 人澡逼| 99re98| 一二三四视频中文字幕在线看| AAAAAAAAA黄片| 99热这里是精品| 日韩影片中文字幕一区二区三区| 国产噜噜噜噜噜久久久久久久久| 91久久精品美女高潮喷水| 猛猛干| 黄片免费视频2019| 超碰人人干| 草b在线| 丝袜狂射91| 97超碰久久| 欧美亚洲尤物久久| 久久久久13| 天天舔天天日天天射| 欧美色97| 岛国激情视频软件| 天美av在线观看| 国产精品久久久三级无码| 熟女被操视频网址| 老熟女区| 婷婷国产精品一区二区| 日本人妻中文字幕| 激情五月天婷婷| 天天天天天天天天综合| 人妻天堂网| 亚洲人妻中文高清| 人人操天天爽| 99999久久精| 无码天天操| 久久久久久中文字幕中文字幕最新| 日日黄色三级网站| 97超碰站| 97WW精品| 中文字幕乱码人妻二区三区| 欧美日韩国内不卡| 韩国轻伦国内自拍一区| 四虎在线视频| 亚洲九月丁香| 伊人玖玖网| 人人操欧美风骚| 秋霞视频一区二区| 亚洲丝袜制服国产91_国语字幕免费观看完整版下载第5集_ | 96AV精品| 四虎AV在线播放| 久久久国产亚洲精品系列| 亚洲免费精品一区| 天天网综合| 美女丝袜激情小说| 日韩精品资源专区二区| 精品精品精品| 果冻传媒A片麻豆熟妇人妻| 日韩国产乱子伦App| 久草精品国产蜜臀 | 蜜桃视频精品一区二区| yazhououmeizongya| 玖玖爱免费观看视频| 农村妇女精品一区二区| 久久久久亚洲三级电影| 精爱久久| 免费av在线播放二区| 欲色影视综合吧| 中文字幕精品免费一区二区| 欧美日日夜夜| 男女啪啪啪18禁网站| 日本成人免费一区二区三区| 免费中文在线| 大香交| www.色婷婷色综合| 亚洲欧美综合网| 天天爽人人综合免费7799| 五月天人妻综合| 婷婷91| 亚洲色阁| 中文字幕乱碼在线| 国产精品爽爽v| 久久超碰av在线| 2020国产精品| 亚州一区二区| 日本青青草在线| 国产精品视频自拍在线| 日韩精品人妻中文字有码在线| 人人看欧美性爱| 熟女熟妇伦久久影院毛片一区二区 | 色小视频蜜乳| 国产日韩久久| 神马午夜久久久| 在线强奷到舒服的无码视频| 欧美色图20P| 日本久久久久久久久| 色屁屁影院www国产| 超碰97欧美日韩| 99自拍视频在线观看| 大香蕉综合网| 91精品国久久久久久无码| 国产成人www免费人成看片| 国产激情在线| 青青操少妇| 国产激情在线观看| 午夜小电影在线插入淫高潮| 久久久久ab| 色色操| 欧美少妇内射| 久久国产乱子伦精品免费女人| 日韩激情视频| 99综合| 在线人成亚洲视频免费观看| 欧美第一页| 欧美男女午夜啪啪| 欧美黑人精品一区二区| 97在线免费| 色97综合中文字幕| 亚洲精品蜜桃久久久一区二区三区| ji熟女.com| 老熟女综合网| 久久久男人的天堂| 后入美女国产| 亚洲精品a人片在线观看视| 九九无码| 中出20p| 精品久久久久久久久久久久| 丁香五月婷婷色| 99国产精品视频尤物| 男人天堂资源| 俺也射| 国产女同性恋视频| 天天综合精品| 日韩精品视频在线观看一卡二卡| 一级黄色性爱裸体视频| 久久老熟女| 人人操人人插 - 百度 - 百度| 97爱欧美| julia高潮后不停追击中出| 综合五月婷婷亚洲一区| 麻豆三极片| 中文字幕乱妇免费视频| 东京热精品97综合网| 丁香五月天婷婷姐| 婷婷久久综合| 青青草天天亲夜夜操网| 99精品视频在线观看免费| 男插女青青影院| 精品久9| 欧美色图另类图片| 无码人妻丰满熟妇区毛片| 97爱b| 美女AV一区二区| 不卡码视频| 97精品国产97久久久久久户外免费| 精品久久久亚洲AV成人网站| 国产美女mm131爽爽爽爽| 亚洲欧美自拍偷拍| 国产女人高潮嗷嗷嗷叫小说| av一区二区三区不卡| 色色毛片| 午夜国产综合视频在线观看 | 久久久久久日韩| 99re热有精品视频国产| 亚洲码在线中文在线观看| 国产精品电影大全| 国产毛片片精品天天看视频| 97视频在线播放| 国产色产精品在线观看| 操国产逼| 日韩操逼性鲍| 日韩欧美国产一区二区三区四区| 东北丰满熟女国产一区| 逼逼逼逼操操操操操操操操操午夜剧场 | 思思热久久成人| 插穴性爱视频在线观看| 免费伦费视频在线观看| 亚洲砖码砖专无区2023| 99热这里只有精品地址 | 久九九九九九九九热| 欧美色九九| 91狠狠| 日本性感人妻91| 国产一级内射无挡观看| caoni国产亚洲av| 色娱乐色呦呦夜夜夜夜av| 我爱搞逼综合网| 97伊人超碰| 97精品国产| 另类小说综合网| 久久久久国产一区二| 国产原创自拍| 五月天婷婷久久| 精久久久| 国产精品小视频一区二区三区| 精品久久久久,69国产成人精| 欧美成人9797| 麻豆 亚洲 97| 噜噜瑟| 欧美一区二区男人天堂| 免费福利视频中文字幕| **一级毛片国产| 97在线国产精品| 久久99草| 欧美中文综合| 亚洲中文一区二区三区| 色婷婷激情| 亚洲激情色片| 欧美翘臀视频网站一区二区三区| 人妻无一区二区三区| 乱伦3P视频| 99这里有精品| 哑洲在线| 影音先锋日本乱伦| 一级黄色影片| 裸体1区| 国产女人视频三四五区| 懂色天天爱天天日天天射天天澡| 婷婷在线播放| 色五月AV在线| 色y情视频免费看| 天天干天天做| 日本天堂在线播放| 岛国A V在线免费看| 亚洲操逼网| 欧美91精彩| 美女天天干| 99热在线播放| 蜜桃臀一区二区三区久久| 沈阳熟女高潮对白视频| 久久女婷| 九九亚洲色在线观看| 亚洲国产精品成人综合| 久99| 欧美成人精品一区二区男人蜜臀| 一级做a爰片性色毛片久久| 久久人妻精品| 色天使AV天堂| 亚欧视频在线| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 综合欧美日本三级| 日韩欧美中文字| 97色伦97色伦国产欧美| 久久久久精| 亚洲中文字幕一区二区| 日本护士高潮| 中文字幕乱在线伦视频中文字幕乱码在线| 十八禁视频网站| 亚洲图片在线| 免费伦费视频在线观看| 亚洲第91页| 久久精品久久九九精品| 精品国产99| 欧美传媒| 自拍二页| 日韩在线性爱免费视频| 国产精品午夜成人福利| 偷拍偷窥与盗摄视频专区| 极品五月天噜噜| 成人小电影网站tex| 狠狠爱综合网| 97超碰欧美精品| 一区二区三区四区色图| 人妻久久一区二区三区 | 欧美综合色综合| 日本性爱少妇| 97精品一区| 中文字幕在线免费观看视频| 亚洲精品乱码久久久久久蜜桃麻豆| 99热99在线播放激情| 欧美亚洲综合999| 偷窥自拍A片| 色色97爱| 亚洲……91| 青青草国产亚洲精品久久| 免费的黄片wwwwww| 国模91| 国产大学生高潮在线播放| 国产黑白丝在线| 开心激情站| 国产一级内射高清视频| 亚熟在线| 日韩欧美中文日韩欧美色| 劲爆欧美人妖三区91| 欧美疯狂做爰xxxx| 96久久久久| 亚洲色图a| 黄色网址在线免费观看| 日韩无码第3页| 亚洲色图在线视频| 日韩精品在线观看观看| 天天热精品| 一本久道久久综合狠狠爱| 中文字幕欧美日韩三级| 黄色不卡视频| 柠檬AV导航| 亚洲无线观看久久| 熟女AV一区| 久久人妻视频| 懂色中文一区二区三区| 欧美青青草视频| 一道本久久棕合爱| 少妇无码av专区线| 欧美午夜熟妇黑人精品91| 肉嘟嘟www视频在线观看高清| 夜夜操夜夜高潮夜夜爽国产精品区| 亚洲欧美国产日本一区二区三区| 91 欧美| 老女人老91妇女老热女| 调教熟妇 久久久久久| 麻豆久久久久久久久丝袜| 噜噜噜在线视频| 91欧美网| 亚洲综合射| 丝袜夫妻自拍| 国产精品视频精品一二| 香伊人在线| 国产免费内射视频| 熟女精品一区二区在线观看| 天天综合,91综合永久| 乱伦av.com| a亚洲欧美色欲| 亚洲做性| 大香蕉综合在线| 宅男91视频在线播放| 国产免费一区在线观看| 99在线免费公开视频| 色欧洲| 亚洲精品九九九九九九| 欧美日韩大陆黑人少妇99| 日韩三级一区 | 亚洲小电影免费涩涩成人在线高清| 老熟女综合网| 蜜桃精品视频一区二区三区| 久久亚州高清| 啪啪91| 亚洲黑丝在线| 欧美日综合| 无码国产精品久久久久| 国产一区二区三区久久久精品| 欧美黑人熟妇精品91| 国产青青综合伊人| 超碰97亚洲区| 久草在| 自拍欧美| 久久曰曰| 久久夜夜夜夜| 麻豆婷婷成人一二三| 97久久久久久久精| 女优视频第10页| 99热66| 久久曰曰| 婷婷丁香六月| 激情婷婷五月天| 干B| 秋霞午夜视频一区二区| 大香蕉中文aV在线| 欧美狠狠弄| 一区二区首页| 欧美一区二区传媒| 超碰天天久久79| 啊啊啊好舒服好爽啊啊啊视频| 精品国产网站| 色婷婷成人综合| 久超超碰| 狠狠2050在线观看| 天天超级碰碰碰| 丝袜色综合| 麻豆天美AV传媒第一页| 人妻另类| 97网色| 国产精品人妻无码久久久互動交流| 蜜臀久久99精品久久久久久无删减 | 中文高清一区二区的| 强奸乱伦AV网址| 欧美大香蕉久| 免费福利视频中文字幕| 亚洲欧美人妻| 人妻无码久久一区二区三区免费| 97久久精品国产| 国产高清不卡视频| 欧美天堂超碰97| 色偷综合| 91操熟女视频| 日韩啪啪视频| 国产JDAV无码视频在线观看| 无码区蜜乳| 国产操偷| 99热66| 国产精品熟女AV中文字幕在线播放| 中文有码第五页| 国产视频第2页| 亚洲蜜臀精品视频久久| 啊啊啊爽爽| 日本十八禁免费看污网站| 国产精品久久久久久 百度| www.91色| 欧美永久激情一区二区| 午夜福利av电影在线| 免费又黄又裸乳的视频| 亚洲欧美中文日韩视频中国语| 五月天激情小说网| 女生自91网站| 91综合天天| 大香蕉免费3| 人妻精品视频一区二区| 超碰97爽| 五月天亚洲网| 天天影视色香欲综合网小说| av网页一区二区三区| 色色色综合| 欧美青青视频| 国产乱子伦久久精品综合一区二区三| 久久久精品91八戒| 日本综合久久| 国产成人主播| 国产伦精品| 九九探花视频在线观看| 九九热免费在线国产视频伊人五月| 97视频新免费| 亚洲最新Av| 欧美一级色| 色拍偷亚洲| 日韩激情电影中文字幕| 久久激情网| 91操人| 国产亚洲精品A在线观看下载| 综合网色| 9999久久久久| 思思视频免费看网站| 性爱视频久久| 欧美线天码中字| 亚洲91在线播放影院| 久久久久国产亚洲一区欧美色图日韩| 青青草导航在线视频| 性爱视频无打码在线观看| 骚货人妻偷情自拍在线视频| 亚洲AV色图一区| 尤物网址| 亚洲色性情三级| 91综合色噜噜| 偷拍伦理视频| 人妻91少妇| 欧美 亚洲 偷拍自拍| 欧美玖玖爱免费玖玖| 强奸国产精品视频| 五月天色电影| 蜜乳AV免费观看| 天天操天天射青青草| 91熟女网| 婷婷九月色| 综合少妇网| 人妻AV在线| 97国产|免费| 东京热免费视频| 老鸭窝在线视频播放| 国产福利影视| 情色五月天就去干| 欧美成人午夜免费福利785| 狠操91,com| 男女激情黄色网址| 免费超碰97久久| 日韩A优精品在线观看| 精品九九九九九九九九九| 秋霞成人一级在线观看| 蜜桃色院一区久久 | 破苞ⅩXXX性无码动漫无码| 欧美AB在线| 欧美日韩精品一区二区三区高清| 伊人黄色视频免费观看| 中文字幕久久亚州无码| 一本大道不卡一二三区| 青久久| 天堂中文日本在线观看| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 北京专精特新企业招聘信息| 亚洲图片另类| 密臀在线免费观看| 中文字幕人成乱码熟女香港| 青青欧洲黑| 国产又大又硬又长又粗| 久区视频| 亚洲情色婷婷五月天| 女欧美一区二三区| 91欧美另类| 91精品无码人妻系列| 天堂网亚洲区手机版| 亚洲另类综合欧美| 强奸抽插av| 精国久久一区二区三区98| 欧美性爱伊人| 美女久久久久久久久久久| 亚洲另类久操网| 久久黄色视频一区二区三区| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 国产女人91精品嗷嗷嗷嗷| 亚洲精品91| 日韩人妻网站| 人妻在线视频| 久草午夜| 色综合久久88色综合久久天天| 亚洲揄拍网| 女人被添高潮免费视频| 欧美高清第一页| 欲射影视| 久久香蕉综合一本到3atv| 九九九九九九九| 亚洲综合97中文网| 成人无码在线超碰网| 大香蕉在线SuP| 成人欧美一区二区三区黑人一| 成人精品在线免费视频| 骚女高跟AV在线| 国产亚洲人妻综合日韩 久久| 久久欲| 亚洲少妇视频| 四虎视频在线观看| 久热无码| 国产 日韩 欧美高清| 另类图片天天影视| 91久久久久久久| 久久久久久久久久久97| 日韩欧美字幕亚洲一区二区 | 欧美日韩成人在线| 操逼免费视频无码国产| 美女诱惑久久| 激情久久日韩精品中文字幕麻豆| 91精品电影18| 久久精品国产72国产精品福利| 亚洲国产美女久久久久| 老熟乱一区二区三区四区| 国产AV人人 夜夜人人澡| 激情综合色| 久久久精品无码亚免费| A片A5445444| 99夜夜操| 高潮9999外国| 蜜臀无码一区二区| 超碰精品| 超碰日本97美女人妻人人玩人人爱| 无码聚合| 无码天天操| 国产黄色小视频网站| 97综合国产| 欧美日韩色| 后入合集| 97国产精品在线观看| 中文久久96| 日日干男人的天堂| 97大色网| 97综合日韩| 岛国AV一区二区电影| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 啊啊啊啊啊好大好舒服想要| 欧美成人9797| 亚洲国产第一页综合视频| 99热伊人| 99亚洲天堂| 99超级碰免费视频| 影音先锋国产精品| 秋霞视频一区二区 | 亚洲色人阁| 伦理第一页| 伊人超碰97| 日韩成人性爱AV| 丁香五月综合| 天天色播亚洲综合网站| www网站黄| 丁香六月啪| 亚洲综合另类| 深夜啪啪啪视频免费| 一二三区在线| 东京热激情视频一二三区| 日本一本一区二区三区四区五区欧美日韩中文字幕 | 狠狠操,使劲操| 大香蕉伊然在亚洲91| 亚洲淫色网中文| 日韩av色图综合| 日本A级视频| 国产不卡中文字幕免费avi| 久久久性爱视频| 老女人老91妇女老热女| 劲爆欧美人妖三区91| 亚洲日本大香蕉1| 怡红院久久老司机|