一、實作效果
選擇本地 pdf 檔案上傳,會生成 pdf 檔案的預覽,點擊保存功能,



二、所用插件
- pdf檔案相關的檔案處理插件:
[email protected] - zip壓縮檔案相關的包:
[email protected] - 檔案保存下載相關的包:
[email protected]
三、相關代碼
vue 中測驗
<!--
* @Date: 2020-10-21 10:44:54
* @information: pdf 轉圖片并下載
-->
<template>
<div id="page09">
<div >
<div >
<input id="input" type="file" accept="application/pdf" @change="convertFile()"/>
</div>
<div >
<div>名稱:{{fileName || '-'}}</div>
<div>大小:{{Number(fileSize).toFixed(2)}}M</div>
<div>頁數:{{filePage}}</div>
<button @click="onExportImg">保存圖片</button>
</div>
</div>
<div id="container"></div>
</div>
</template>
<script>
import PDFJS from 'pdfjs-dist'
import JSZIP from 'jszip'
import FileSaver from 'file-saver'
export default {
data() {
return {
// pdf地址
pdfPath2: `https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf`,
// arrayBuffer
arrayBuffer: null,
// 檔案名稱
fileName: null,
// 檔案大小
fileSize: 0,
// 檔案頁數
filePage: 0,
}
},
methods: {
/**
* 讀取檔案內容
*/
convertFile() {
let file = document.getElementById('input').files
if(!file.length) return;
let {name, size} = file[0]
Object.assign(this, {fileName: name, fileSize: size/1024/1024})
// 使用FileReader物件,web應用程式可以異步的讀取存盤在用戶計算機上的檔案(或者原始資料緩沖)內容,可以使用File物件或者Blob物件來指定所要處理的檔案或資料
let fileReader = new FileReader()
// 異步按位元組讀取檔案內容,結果用ArrayBuffer物件表示
fileReader.readAsArrayBuffer(file[0])
fileReader.onload = (e) => {
let arrayBuffer = this.arrayBuffer = e.target.result
// 創建canvas節點
this.createCanvas(arrayBuffer)
}
},
/**
* 創建canvas
*/
createCanvas(val) {
// 清空節點下資料
document.getElementById('container').innerHTML = ''
// 使用getTextContent獲取pdf內容
PDFJS.getDocument(val).promise.then(el => {
let filePage = this.filePage = el.numPages
for(let i = 1; i <= filePage; i ++) {
let canvas = document.createElement('canvas')
canvas.id = `pageNum-${i}`
let context = canvas.getContext('2d')
document.getElementById('container').append(canvas)
// 渲染canvas
this.openPage(el, i, context)
}
})
},
/**
* 渲染canvas
*/
openPage(pdfFile, pageNumber, context) {
// 獲取PDF檔案中的各個頁面
pdfFile.getPage(pageNumber).then(page => {
// 設定展示比例
let scale = 3
// 獲取pdf尺寸
let viewport = page.getViewport(scale)
let canvas = context.canvas
canvas.width = viewport.width
canvas.height = viewport.height
canvas.style.width = "100%"
canvas.style.height = "100%"
let model = {
canvasContext: context,
viewport: viewport,
}
// 渲染PDF
page.render(model)
})
},
/**
* 保存圖片
*/
onExportImg() {
if(!this.arrayBuffer) {
alert(`請上傳pdf檔案`)
return;
}
let jszip = new JSZIP()
// 解壓縮后的檔案夾名稱
let images = jszip.folder("images")
let eleList = document.querySelectorAll('canvas')
// 遍歷所有canvas節點
for(let i = 0; i < eleList.length; i ++) {
let canvas = document.getElementById(`pageNum-${i+1}`)
// 向此檔案夾中加入檔案
// toDataURL() 方法回傳一個包含圖片展示的 data URI ,可以使用 type 引數其型別,默認為 PNG 格式,圖片的解析度為96dpi
images.file(`image-${i+1}.png`, this.dataURLtoBlob(canvas.toDataURL("image/png", 1.0)), {
base64: true
})
}
// 生成一個zip檔案
jszip.generateAsync({
type: "blob"
}).then((content) => {
// 使用 FileSaver 保存下載 zip 檔案
FileSaver.saveAs(content, "pdfToImages.zip");
})
},
/**
* dataURL 轉成 Blob
*/
dataURLtoBlob(val) {
let arr = val.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n --) {
// charCodeAt() 方法可回傳指定位置的字符的 Unicode 編碼,這個回傳值是 0 - 65535 之間的整數
u8arr[n] = bstr.charCodeAt(n)
}
// new Blob(blobParts, [options]) 引數說明:
// 1. blobParts:陣列型別,陣列中的每一項連接起來構成Blob物件的資料,陣列中的每項元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString
// 2. options:可選項,字典格式型別,可以指定如下兩個屬性:
// (1) type,默認值為 "",它代表了將會被放入到blob中的陣列內容的MIME型別,
// (2) endings,默認值為"transparent",用于指定包含行結束符\n的字串如何被寫入, 它是以下兩個值中的一個: "native",表示行結束符會被更改為適合宿主作業系統檔案系統的換行符; "transparent",表示會保持blob中保存的結束符不變
return new Blob([u8arr], { type: mime })
},
},
created() {
},
mounted() {
}
}
</script>
<style lang="scss">
#page09 {
width: 1000px;
margin: 0 auto;
.info-box {
position: relative;
.input {
margin: 15px 0;
#input {
width: 100%;
height: 100%;
cursor: pointer;
}
}
.cell {
margin: 15px 0;
display: flex;
justify-content: space-around;
div {
margin-right: 20px;
}
}
}
#container {
width: 100%;
min-height: 850px;
margin: 0 auto;
border: 1px solid #eee;
border-radius: 10px;
canvas {
margin-bottom: 10px;
border: 1px solid #ff6700;
border-radius: 10px;
}
}
}
</style>
四、相關知識點
1. 使用 FileReader 進行檔案讀取
[HTML5] FileReader物件
(1)創建實體
let fileReader = new FileReader()
(2)方法
| 方法定義 | 描述 |
|---|---|
| abort():void | 終止檔案讀取操作 |
| readAsArrayBuffer(file):void | 異步按位元組讀取檔案內容,結果用ArrayBuffer物件表示 |
| readAsBinaryString(file):void | 異步按位元組讀取檔案內容,結果為檔案的二進制串 |
| readAsDataURL(file):void | 異步讀取檔案內容,結果用data:url的字串形式表示 |
| readAsText(file,encoding):void | 異步按字符讀取檔案內容,結果用字串形式表示 |
(3)事件: FileReader 通過異步的方式讀取檔案內容,結果均是通過事件回呼獲取,
| 方法定義 | 描述 |
|---|---|
| onabort | 當讀取操作被中止時呼叫 |
| onerror | 當讀取操作發生錯誤時呼叫 |
| onload | 當讀取操作成功完成時呼叫 |
| onloadend | 當讀取操作完成時呼叫,不管是成功還是失敗 |
| onloadstart | 當讀取操作將要開始之前呼叫 |
| onprogress | 在讀取資料程序中周期性呼叫 |
2. 使用 canvas 的 toDataURL() 方法回傳 包含 data URI 的DOMString
MDN: HTMLCanvasElement.toDataURL()
let canvas = document.getElementById(`canvas`)
// 引數說明:
// 1. type(可選):圖片格式,默認為 image/png
// 2. encoderOptions(可選):在指定圖片格式為 image/jpeg 或 image/webp的情況下,可以從 0 到 1 的區間內選擇圖片的質量,如果超出取值范圍,將會使用默認值 0.92,其他引數會被忽略,
let result = canvas.toDataURL("image/png", 1.0)
3. ArrayBuffer 二進制陣列
ArrayBuffer,二進制陣列
(1) JS 中的二進制資料格式,例:ArrayBuffer,Uint8Array,DataView,Blob,File 及其他,
基本的二進制物件是 ArrayBuffer —— 對固定長度的連續記憶體空間的參考,
(2)如要操作 ArrayBuffer,我們需要使用“視圖”物件, 視圖物件本身并不存盤任何東西,它是一副“眼鏡”,透過它來解釋存盤在 ArrayBuffer 中的位元組,例如下:
| 視圖型別 | 說明 |
|---|---|
| Uint8Array | 將 ArrayBuffer 中的每個位元組視為 0 到 255 之間的單個數字(每個位元組是 8 位,因此只能容納那么多),這稱為 “8 位無符號整數”, |
| Uint16Array | 將每 2 個位元組視為一個 0 到 65535 之間的整數,這稱為 “16 位無符號整數”, |
| Uint32Array | 將每 4 個位元組視為一個 0 到 4294967295 之間的整數,這稱為 “32 位無符號整數”, |
| Float64Array | 將每 8 個位元組視為一個 5.0x10-324 到 1.8x10308 之間的浮點數, |
3. Blob
細說Web API中的Blob
(1)概述: Blob 物件表示一個不可變、原始資料的類檔案物件,它的資料可以按文本或二進制的格式進行讀取,也可以轉換成 ReadableStream 來用于資料操作,Blob 表示的不一定是JavaScript原生格式的資料,File 介面基于Blob,繼承了 blob 的功能并將其擴展使其支持用戶系統上的檔案,
(2)創建 Blob 物件
// 引數說明
// 1. blobParts: 陣列型別,陣列中的每一項連接起來構成Blob物件的資料,陣列中的每項元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString
// 2. options:可選項,字典格式型別,可以指定如下兩個屬性:
type,默認值為 "",它代表了將會被放入到blob中的陣列內容的MIME型別,
endings,默認值為"transparent",用于指定包含行結束符\n的字串如何被寫入, 它是以下兩個值中的一個: "native",表示行結束符會被更改為適合宿主作業系統檔案系統的換行符; "transparent",表示會保持blob中保存的結束符不變,
let blob = new Blob(blobParts[, options])
let data1 = "a"
let data2 = { "name": "abc" }
let blob1 = new Blob([data1])
let blob2 = new Blob([JSON.stringify(data4)])
let blob3 = new Blob([data4])
console.log(blob1); // Blob {size: 1, type: ""}
console.log(blob2); // Blob {size: 14, type: ""}
console.log(blob3); // Blob {size: 15, type: ""}
size代表Blob 物件中所包含資料的位元組數,這里要注意,使用字串和普通物件創建Blob時的不同,blob4使用通過JSON.stringify把data4物件轉換成json字串,blob5則直接使用data4創建,兩個物件的size分別為14和15,blob4的size等于14很容易理解,因為JSON.stringify(data4)的結果為:"{"name":"abc"}",正好14個位元組(不包含最外層的引號),blob5的size等于15是如何計算而來的呢?實際上,當使用普通物件創建Blob物件時,相當于呼叫了普通物件的toString()方法得到字串資料,然后再創建Blob物件,所以,blob5保存的資料是"[object Object]",是15個位元組(不包含最外層的引號),
(3)Blob 方法: slice()
(4)Blob使用場景
- 分片上傳
- Blob URL
參考:PDF轉成圖片
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/186254.html
標籤:JavaScript
上一篇:js的物件
