开发钉钉内部H5应用使用iframe标签,预览pdf会跳转到了下载页面

210 阅读2分钟

场景:开发钉钉内部应用时有PDF/附件预览需求,但是发现使用iframe标签嵌套会自动下载

情况:自动弹出文件保存 或者 页面显示下载

1. 官方回复

出于安全考虑,iframe中不支持预览pdf,在使用Chrome iframe预览PDF时,存在以下潜在的安全问题:

  1. 恶意PDF文件:如果PDF文件本身存在恶意代码,则通过iframe预览可能会导致浏览器被攻击者控制,进而对用户计算机进行攻击。

  2. CSRF(跨站请求伪造)攻击:攻击者可以通过制造恶意网页,在用户访问时向iframe中注入CSRF攻击代码,从而盗取用户敏感信息。

  3. 点击劫持攻击:攻击者可以通过遮盖在iframe上的透明图层,诱导用户在不知情的情况下点击恶意链接或按钮,从而完成攻击。

  4. XSS(跨站脚本攻击)漏洞:如果iframe中的PDF文件存在XSS漏洞,则攻击者可以通过注入恶意脚本,获取用户敏感信息或窃取用户凭证。

  5. 信息泄露:在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>

如果对您有帮助的的请点点关注,感谢您的支持