IPhone和安卓預覽word和PDF文件之路

前言

這篇文章主要是爲了總結一下最近作微信內置瀏覽器預覽文件😁(word和pdf)在不一樣操做系統的問題。在IPhone微信內置瀏覽器中,基本能夠預覽各式各樣的文件格式,可是在安卓就不行了,打開文件地址就跳轉到瀏覽器下載頁面了。如下就是本人的踩坑之路。css

~~敢問路在何方,路就在腳下html

官網demo( mozilla.github.com/pdf.js/web/… ),其原理是繪製成canvas前端

解決方式

  1. PDF在ios和安卓的預覽
  • 安卓:PDF.JS(地址 github.com/mozilla/pdf… ) 來解析pdf文件(本身的頁面,能夠轉發分享,經過JS-SDK設置)
  • IOS: 微信自帶的預覽功能(不能分享,由於這個頁面是微信本身的,因此改不了),也能夠改爲PDFJS來實現跟安卓同樣的(微信自己的若是圖文複雜的word預覽也會有點錯亂)
  1. Word在ios和安卓的預覽
  • 後端將word轉成PDF文件,前端在經過PDF實現ios和安卓的預覽
  • 後端能夠轉換成圖片,這樣就能夠直接渲染了
    注:前端我暫時沒找到好的辦法將word轉換成PDF😁,因此經過後端轉換來實現。後端用linux轉的話若是圖文比較複雜的話會出現圖文錯亂的問題,因此建議經過購買Window系統的服務器來轉換(坑),也能夠在阿里雲市場購買服務(👀不太推薦,仍是有點小貴的)

PDFJS準備工做

  • pdf.js能夠從github上clone下來,而後本地gulp生成可用的pdf.js和pdf.worker.js(參考readme便可)。不過,本人推薦仍是用npm安裝,npm install pdfjs-dist --S,而後在項目中經過import PDFJS from 'pdfjs-dist引用就能夠用了
  • pdf.js不能處理跨域文件和本地文件,因此本地調試的時候應該請求服務器的文件,若是請求的是遠程服務器,存在跨域,那就須要在config/index.js中配置一下代理
proxyTable: {
      '/media': {
        target: 'https://xxxx.cn', // 換成正確的服務器域名
        changeOrigin: true,
        pathRewrite: {
          '^/media': '/media'
        }
      }
    }
原文:https://blog.csdn.net/u010419337/article/details/79535131
複製代碼

這樣的話請求裏面包含media的會被替換成target那個域名,OK,完美👌linux

核心代碼

項目安裝好pdfjs-dist後就經過下面代碼引入文件ios

import PDFJS from 'pdfjs-dist'
import { TextLayerBuilder } from 'pdfjs-dist/web/pdf_viewer'
import 'pdfjs-dist/web/pdf_viewer.css'
PDFJS.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.js'
複製代碼

一和四這兩個文件包含了獲取、解析和展現PDF的方法,可是解析和渲染PDF須要較長的時間,因此pdfjs經過依賴HTML5的web Worker,從而從主線程中移除大量的CPU操做來提高性能。 二和三的文件主要是爲了來實現渲染出來的pdf能夠複製裏面的文字,也至關於將裏面的圖文用真實的文字和圖片經過html渲染出來。若是沒有這一步的話生成的是一個個canvasgit

// 頁面上寫個容器
div class="file_preview" ref="filePreview">
    <div id="container"></div>
</div>
複製代碼
let container
let url = '你的pdf文件地址.pdf'(線上環境真實存在的文件)

// 經過getDocument以塊的形式請求文檔,返回Promise
PDFJS.getDocument(url).then((pdf) => {
    // 獲取容器
    container = document.getElementById('container')
    // 獲取pdf的總頁數
    let num = pdf.numPages
    // 執行核心解析和渲染代碼
    this.renderPDF(pdf, num)
  }).catch(err => {
    console.log(err)
  })
複製代碼

解析渲染函數github

renderPDF (pdf, num) {
      for (let i = 1; i<= num; i++) {
        let pageDiv
        pdf.getPage(i).then((page) => {
         // 設置PDF尺寸,若是渲染出來的模糊的話這個稍微能夠調大點,可是要給容器的canvas設置個樣式,本人親測過,以下樣式設置
          var viewport = page.getViewport(2)
          pageDiv = document.createElement('div')
          pageDiv.setAttribute('id', 'page-' + (page.pageIndex + 1))
          pageDiv.setAttribute('style', 'position: relative')
          container.appendChild(pageDiv)
          var canvas = document.createElement('canvas')
          pageDiv.appendChild(canvas)
          var context = canvas.getContext('2d')
          canvas.width = viewport.width
          canvas.height = viewport.height
            
          var renderContext = {
              canvasContext: context,
              viewport: viewport
          };
          page.render(renderContext).then(() => {
            // 返回PDF頁面上的文本片斷,爲了實現文本複製
            return page.getTextContent()
          }).then((textContent) => {
            // 建立文本圖層div
            const textLayerDiv = document.createElement('div')
            textLayerDiv.setAttribute('class', 'textLayer')
            // 將文本圖層div添加至每頁pdf的div中
            pageDiv.appendChild(textLayerDiv)
            
            // 建立新的TextLayerBuilder實例
            var textLayer = new TextLayerBuilder({
                textLayerDiv: textLayerDiv,
                pageIndex: page.pageIndex,
                viewport: viewport
            })         
            textLayer.setTextContent(textContent)       
            textLayer.render()
          })
        })
      }
    }
複製代碼
<style scoped>
.file_preview {
  width: 100%;
  overflow: hidden;
  background-color: #ffffff;
  padding: 8px 10px;
}
</style>
<style>
.file_preview canvas {
  width: 100%;
  height: 100%;
}
</style>
複製代碼

分析以上函數用到的方法web

參考(www.cnblogs.com/lalalagq/p/…npm

  • getDocument():用於異步獲取PDf文檔,發送多個Ajax請求以塊的形式下載文檔。它返回一個Promise,該Promise的成功回調傳遞一個對象,該對象包含PDF文檔的信息,該回調中的代碼將在完成PDf文檔獲取時執行
  • getPage():用於獲取PDF文檔中的各個頁面
  • getViewport():針對提供的展現比例,渲染PDF的頁面尺寸
  • render():渲染PDF

文本複製

以上引入的第三和第四個文件,就是用來解決文本複製的問題,經過使用Text-Layer來渲染。PDF.js支持在使用Canvas渲染的PDF頁面上渲染文本圖層。然而,這個功能須要用到額外的兩個文件:text_layer_builder.jstext_layer_builder.css,引入這兩個文件gulp

import { TextLayerBuilder } from 'pdfjs-dist/web/pdf_viewer'
import 'pdfjs-dist/web/pdf_viewer.css'
複製代碼

主要代碼如上「解析和渲染函數」

PDF.JS核心API的做用

  • page.render():返回一個當PDF成功渲染到頁面上時的Promise,能夠經過使用成功回調來渲染文字圖層
  • page.getTextContent():得到PDF頁面上的文本片斷
  • TextLayerBuilder:有兩個重要的方法,setTextContent()用於設置page.getTextContent()函數返回的文本片斷;render()用於渲染文本圖層

總結

強大的PDF.JS基本實現了預覽PDF的問題,缺點是官網文檔太過於精簡了😂,不過以上基本已經能夠實現大部分需求了。產品再給你提需求還怕嗎!!😁

相關文章
相關標籤/搜索