使用ueditor上传附件(pdf, mp4等)可直接预览

需求背景

        最近遇到一个需求,在使用富文本框编辑文章内容时,需要上传附件,同时上传的这个附件需要以附件的格式或者直接预览的方式展现。

实现基础

        这个项目主要是基于vue2,使用了百度的富文本编辑器UEditor,其中对这个富文本编辑框的上传附件模块做了一些小封装,这些都忽略不计(因为大致的逻辑还是一样的,处理上传附件,将上传的附件通过ueditor内置的.execCommand("insertHTML",html)插入到对应的文章内部)。所以此处不做赘述。

        其中对pdf进行预览的模块没有使用iframe或者embed等标签进行处理,原因就是其高度不会正常撑开,而这个过程中不好对pdf进行高度计算,所以总是会出现滚动条等不利于展示的因素。最后采用的是PDF.js,大致的实现过程就是通过pdf.js对pdf文件进行解析,从中转为canvas再通过canvas.toDataURL()通过img标签进行渲染该pdf文件;实测效果最佳,页面平铺。

实现过程

1.安装对应的pdf.js插件

版本最好注意一下,否则会有一些问题;笔者安装的是2.2.228版本

npm install pdfjs-dist@2.2.228

2.组件中引入:

import * as pdfjsLib from "pdfjs-dist/build/pdf";
// globalworker 设置,用 CDN 的资源;如果你本地的也可以那就可以配置成本地的 "pdfjs-dist/build/pdf.worker.min.js"
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js";

3.处理对应的逻辑

以下是上传附件成功之后触发的事件,当上传附件成功之后 传入results为附件list,其中每个对象赋予了type:文件类型,preview:是否预览,是则展示预览的,否则展示附件格式;其他参数不做赘述

handleResourceDialogOk (results) {
      if (results && results.length > 0) {
        const r = results[0];
        let html = '';
        const editor = window.UE.getEditor(this.editorId)
        results.forEach(r => { // TODO
          if (r.resourceType == 'video' && r.preview) {
            html += '<video controls="controls" style="width: 720px; height: 480px; margin: 0 auto;" src="' + r.src + '"></video>';
          }else if (r.resourceType == 'file' && r.preview && r.type == 'pdf') {
              this.loadPdf(r.src, editor)
              return
          } else if (r.resourceType == 'image') {
            html += '<p><img src="' + r.src + '" iurl="' + r.path + '" class="art-body-img" /></p>'
          } else {
            html += '<p><a href="' + r.src + '" iurl="' + r.path + '" target="_blank" class="art-body-' + r.resourceType + '">' + r.name + '</a></p>'
          }
        });
        if (html && html.length > 0) {
          editor.execCommand("insertHTML",html);
        }
      }
    },

随后就是处理pdf的代码如下:

 /**
  * pdfUrl 为文件所在路径
  * editor 为富文本编辑器实例
  */
async loadPdf(pdfUrl, editor) {
      let images = []
      try {
        const pdf = await pdfjsLib.getDocument(pdfUrl).promise;
        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          const page = await pdf.getPage(pageNum);
          const viewport = page.getViewport({ scale: 1.5 });
          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          canvas.height = viewport.height;
          canvas.width = viewport.width;
          
          await page.render({
            canvasContext: context,
            viewport: viewport,
          }).promise;
          
          const imageURL = canvas.toDataURL();
          images.push(imageURL);
        }
      } catch (error) {
        console.error('PDF 加载失败:', error);
      }
      const that = this
      this.$nextTick(() => {
        let html = '';
          images.forEach(i => {
            html += '<p style="text-align:center;"><img src="' + i + '" /><p>'
          });
          editor.execCommand("insertHTML",html, true);
      })
    },

理论上 差不多就可以实现了 但是由于笔者的这个项目 前人对ueditor做了一些处理,导致有一些问题,随着排查的同时也对对应的一些配置进行了修改;

踩坑修改过程

1.当插入html的过程中第三个参数是判断是否要过滤插入的代码,这个时候我还没意识到过滤的问题所在,思来想去先不做过滤好了,随即传递了第三个参数为true,ok,插入dom的时候正常了,页面也能正常去渲染。但是到了回显的时候,又找不到了

2.回显这个预览的pdf,回显的时候会调用实例的setContent方法渲染对于的html内容;

this.editor.setContent(this.value);

这个时候,我发现他不回显了;随即又跑到ueditor.all.js中查看,找到该函数

大致代码如下

它回显的时候在8088行处又又又根据制定的规则去过滤了 我便给此处打了一个标签,对此处进行重点排查;下方的是过滤的函数

其中有个对img的case判断

它将base64的去除了,所以导致上面两个阶段都不会正常处理图片的格式渲染,随即我将此处过滤机制注释掉,后面就很流畅的进行pdf预览等操作啦

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值