场景:开发钉钉内部应用时有PDF/附件预览需求,但是发现使用iframe标签嵌套会自动下载
情况:自动弹出文件保存 或者 页面显示下载
1. 官方回复
出于安全考虑,iframe中不支持预览pdf,在使用Chrome iframe预览PDF时,存在以下潜在的安全问题:
-
恶意PDF文件:如果PDF文件本身存在恶意代码,则通过iframe预览可能会导致浏览器被攻击者控制,进而对用户计算机进行攻击。
-
CSRF(跨站请求伪造)攻击:攻击者可以通过制造恶意网页,在用户访问时向iframe中注入CSRF攻击代码,从而盗取用户敏感信息。
-
点击劫持攻击:攻击者可以通过遮盖在iframe上的透明图层,诱导用户在不知情的情况下点击恶意链接或按钮,从而完成攻击。
-
XSS(跨站脚本攻击)漏洞:如果iframe中的PDF文件存在XSS漏洞,则攻击者可以通过注入恶意脚本,获取用户敏感信息或窃取用户凭证。
-
信息泄露:在iframe中预览PDF文件时,可能会泄露用户的浏览历史记录、IP地址、浏览器版本等敏感信息,给用户带来潜在的隐私风险。
chrome官方因为安全风险,已不支持这个功能
2. 官方推荐方案
官方回复:
目前钉钉pc win端iframe里无法直接预览的,只有跳转浏览器来打开页面预览了,跳转浏览器的话可以参考这个协议来拼接url:
open.dingtalk.com/document/is…
3. 小编推荐
在外部打开虽然可以满足部分需求,但是在系统体验上会大打折扣。
于是我便有了一个新的思路:将PDF转成图片再渲染到页面上
技术使用:vite + vue3
组件代码如下:
<template>
<div ref="showpdfRef" class="preview-container" style="width: 100%;height: 240px;overflow: scroll"></div>
</template>
<script setup>
import { ref } from 'vue';
import { getDocument } from 'pdfjs-dist/legacy/build/pdf.mjs';
import 'pdfjs-dist/build/pdf.worker.mjs';
const props = defineProps({
pdfSrc: {
type: String,
default: '',
},
});
const pdfSrc = toRef(props, 'pdfSrc');
const showpdfRef = ref(null);
const pdfPath = computed(() => {
// console.log('-----', import.meta.env.VITE_BASE_URL + pdfSrc.value)
return pdfSrc.value;
})
const loadingTask = getDocument(pdfPath.value);
loadingTask.promise
.then(async (pdf) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
// 循环遍历每一页pdf,将其转成图片
for (let i = 1; i <= pdf._pdfInfo.numPages; i++) {
// 获取pdf页
const page = await pdf.getPage(i);
// 获取页的尺寸
const viewport = page.getViewport({ scale: 1 });
// 设置canvas的尺寸
canvas.width = viewport.width;
canvas.height = viewport.height;
// 将pdf页渲染到canvas上
await page.render({ canvasContext: context, viewport: viewport }).promise;
// 将canvas转成图片,并添加到页面上
const img = document.createElement('img');
img.src = canvas.toDataURL('image/png');
showpdfRef.value.appendChild(img);
}
})
.then(
function () {
console.log('# End of Document');
},
function (err) {
console.error('Error: ' + err);
},
);
</script>
<style scoped>
.preview-container {
::-webkit-scrollbar {
width: 0;
height: 0;
}
}
</style>
如果对您有帮助的的请点点关注,感谢您的支持