今天一天对当前可用的pdf预览插件做了测试,主要需求是只能预览不能下载,但对于前端来说,没有绝对的禁止,这里只罗列实现方式。
目前采用vue3版本为:3.2.37
- iframe
- vue-office
- pdfjs-dist
iframe
先说最简单的,iframe可以直接展示pdf文件,所以如果不作禁止预览等操作,iframe是最合适的。
<el-dialog
v-model="previewOtherUpload"
reset-drag-position
draggable
sticky
:title="_options.imgName || '详情'"
footer-hide
class-name="vertical-center-modal"
>
<div
@contextmenu.prevent
style="user-select: none;"
>
<iframe
ref="iframe"
:src="`${modelValue}#toolbar=0`"
width="100%"
height="600px"
@load="onIframeLoad"
>
</iframe>
</div>
</el-dialog>
<script setup>
const modelValue = ref('https://501351981.github.io/vue-office/examples/dist/static/test-files/test.pdf')
let previewOtherUpload = ref(false);
const iframe = ref(null)
const clickShow = () => {
previewOtherUpload.value = true;
}
// 尝试在iframe加载完毕后,进行右键禁用,但实际需要通过postmessage来处理,所以这里无实际用处
const onIframeLoad = () => {
try {
console.log('iframe 已加载', iframe.value.contentWindow.window);
if (iframe.value.contentWindow.document) {
iframe.value.contentWindow.document.addEventListener('contextmenu', (e) => e.preventDefault());
}
} catch (error) {
console.error('无法访问 iframe 内容:', error);
}
}
</script>
vue-office
安装
#docx文档预览组件
npm install @vue-office/docx vue-demi@0.14.6
#excel文档预览组件
npm install @vue-office/excel vue-demi@0.14.6
#pdf文档预览组件
npm install @vue-office/pdf vue-demi@0.14.6
#pptx文档预览组件
npm install @vue-office/pptx vue-demi@0.14.6
如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
npm install @vue/composition-api
我们如果只预览pdf,则安装 npm install @vue-office/pdf vue-demi@0.14.6
<el-dialog
v-model="previewOtherUpload"
reset-drag-position
draggable
sticky
:title="_options.imgName || '详情'"
footer-hide
class-name="vertical-center-modal"
>
<div
@contextmenu.prevent
style="user-select: none;"
>
<VueOfficePdf
:src="modelValue"
/>
</div>
</el-dialog>
<script setup>
import VueOfficePdf from '@vue-office/pdf'
const modelValue = ref('https://501351981.github.io/vue-office/examples/dist/static/test-files/test.pdf')
let previewOtherUpload = ref(false);
const clickShow = () => {
previewOtherUpload.value = true;
}
</script>
pdfjs-dist
这是目前最麻烦的一个插件,一定先确定下载的版本"pdfjs-dist": “2.16.105”,我用的是这个,否则下面的workerSrc设置会有问题。
<el-dialog
v-model="previewOtherUpload"
reset-drag-position
draggable
sticky
:title="_options.imgName || '详情'"
footer-hide
class-name="vertical-center-modal"
>
<div
id="pdf-view"
@contextmenu.prevent
style="user-select: none;"
>
<canvas v-for="page in state.pdfPages" :key="page" id="pdfCanvas" />
<div id="text-view"></div>
</div>
</el-dialog>
<script setup>
import { computed, reactive, ref, watch, nextTick } from "vue";
import * as pdfjsViewer from 'pdfjs-dist/web/pdf_viewer.js'
import 'pdfjs-dist/web/pdf_viewer.css'
import * as PDF from 'pdfjs-dist'
// 设置 pdf.worker.js 路径
PDF.GlobalWorkerOptions.workerSrc = '../../../node_modules/pdfjs-dist/build/pdf.worker.js';
let pdfDoc = null;
const modelValue = ref('https://501351981.github.io/vue-office/examples/dist/static/test-files/test.pdf')
let previewOtherUpload = ref(false);
const clickShow = () => {
loadFile(modelValue)
previewOtherUpload.value = true;
}
const loadFile = (url) => {
PDF.getDocument({
url,
cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/',
cMapPacked: true,
}).promise.then((pdf) => {
pdfDoc = pdf
// 获取pdf文件总页数
state.pdfPages = pdf.numPages
nextTick(() => {
renderPage(1) // 从第一页开始渲染
})
})
}
const renderPage = (num) => {
pdfDoc.getPage(num).then((page) => {
const canvas = document.getElementById('pdfCanvas')
const ctx = canvas.getContext('2d')
const viewport = page.getViewport({ scale: state.pdfScale })
canvas.width = viewport.width
canvas.height = viewport.height
const renderContext = {
canvasContext: ctx,
viewport
}
page.render(renderContext)
})
}
</script>
插件样式也不好调整,不推荐。
总结:
最后还是使用了第二种方式,作为禁止下载的展示。