文档在线转PDF,Vue2接收PDF文件流预览

需求

文档在线预览功能,类似于vue-office-docx这样的插件,由于doc格式不兼容,所以体验效果不好,退而求其次,把所有文档(doc、ppt、xls等)全部在线转为PDF,再由前端接收并展示。

解决方案

使用 liberoffice 命令行将doc等文档转换为pdf文件并另存为到临时文件,vue前端接收pdf文件流并用vue-office-pdf插件完成预览。

文末提供更简便方法~

后台

pom

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-exec</artifactId>
   <version>1.3</version>
</dependency>

controller

/**
 * 转 pdf 下载
 * @param ossId
 * @param response
 * @throws IOException
 */
@GetMapping("/downloadPdf/{ossId}")
public void downloadPdf(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
    iSysOssService.downloadToPdf(ossId,response);
}

service

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.xmlbeans.impl.common.IOUtil;
import java.util.concurrent.Semaphore;

/**
 * 转pdf 下载
 * @param ossId
 * @param response
 * @throws IOException
 */
public void downloadToPdf(Long ossId, HttpServletResponse response) throws IOException {
    SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
    if (ObjectUtil.isNull(sysOss)) {
        throw new ServiceException("文件数据不存在!");
    }
    String pdfName = sysOss.getOriginalName().substring(0, sysOss.getOriginalName().indexOf(".")) + ".pdf";

    FileUtils.setAttachmentResponseHeader(response, pdfName);
    response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
    try {

        DefaultExecutor exec = new DefaultExecutor();
        File tempFolder = new File(System.getProperty("java.io.tmpdir"), "office2pdf-" + IdUtil.fastSimpleUUID());
        if (!tempFolder.exists()) {
            tempFolder.mkdirs();
        }
        String orginName = tempFolder.getAbsolutePath() + File.separator + sysOss.getOriginalName();
        //复制 本地
        OssClient storage = OssFactory.instance();
        try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
            int available = inputStream.available();
            OutputStream fileOutputStream = new FileOutputStream(orginName);
            IoUtil.copy(inputStream, fileOutputStream, available);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        // 同步等待
        Semaphore semaphore = new Semaphore(1);
        semaphore.acquire();
        ExecuteResultHandler erh = new ExecuteResultHandler() {
            @Override
            public void onProcessComplete(int i) {
                semaphore.release();
                //转换完成逻辑
            }
            @Override
            public void onProcessFailed(ExecuteException e) {
                semaphore.release();
            }
        };
        String command = "soffice --invisible --convert-to pdf --outdir \"" + tempFolder.getAbsolutePath() + "\" \""
            + orginName + "\"";
        exec.execute(CommandLine.parse(command), erh);
        // 等待执行完成
        semaphore.acquire();

        //response 下载
        File file = new File(tempFolder.getAbsolutePath() + File.separator + pdfName);
        FileInputStream inputStream = new FileInputStream(file);
        int available = inputStream.available();
        IoUtil.copy(inputStream, response.getOutputStream(), available);
        response.setContentLength(available);
    } catch (Exception e) {
        throw new ServiceException(e.getMessage());
    }
}

前台

// pdf文档预览组件

npm install @vue-office/pdf

<template>  
    <!--   pdf 直接预览   -->
      <div>
        <vue-office-pdf
          :src="pdfUrl"
          @rendered="renderedHandler"
          @error="errorHandler"
        />
      </div>
</template>

//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'

export default {
  components:{
    VueOfficePdf,
  },
  data() {
    return {
      pdfUrl: "",
      fullscreenLoading: false,
    }
  },
  methods: {
    /** pdf */
    renderedHandler() {
      console.log("渲染完成")
      this.fullscreenLoading = false
    },
    errorHandler() {
      console.log("渲染失败")
      this.fullscreenLoading = false
    },
    /** 在线转PDF */
    ossPdf(ossId) {

      this.fullscreenLoading = true
      var url = process.env.VUE_APP_BASE_API + '/file/downloadPdf/' + ossId
      axios({
        method: 'get',
        url: url,
        responseType: 'blob',
        headers: { 'Authorization': 'Bearer ' + getToken() }
      }).then((res) => {
        const isBlob = blobValidate(res.data);
        if (isBlob) {

          let fileURL = null
          var blob = new Blob([res.data], {type: 'application/pdf'})
          if (window.createObjectURL != undefined) { // basic
            fileURL = window.createObjectURL(blob);
          }else if (window.webkitURL != undefined) { // webkit or chrome
            try {
              fileURL = window.webkitURL.createObjectURL(blob);
            } catch (error) {console.log(error)}
          } else if (window.URL != undefined) { // mozilla(firefox)
            try {
              fileURL = window.URL.createObjectURL(blob);
            } catch (error) {console.log(error)}
          }
          console.log("PDF文件地址0 ", fileURL)
          this.pdfUrl = fileURL

        } else {
          this.printErrMsg(res.data);
        }
      }).catch((r) => {
        console.error(r)
        Message.error('下载文件出现错误,请联系管理员!')
      })
    },
}

扩展

kkFileView-文件文档在线预览

该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等

docker安装并运行

需要预览文件时,只需要调用浏览器打开本项目的预览接口,并传入须要预览文件的url

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为AI语言模型,我不能够执行实时的代码和提供实时的服务。但是,如果您想要在Vue中实现在线预览PDF文件,您可以使用以下步骤: 1. 安装pdf.js库:`npm install pdfjs-dist` 2. 在Vue组件中引入pdf.js:`import pdfjsLib from 'pdfjs-dist'` 3. 创建一个方法来获取PDF文件并将其换为可预览的URL: ``` previewPdf(pdfData) { return new Promise((resolve, reject) => { const loadingTask = pdfjsLib.getDocument({ data: pdfData }) loadingTask.promise.then((pdf) => { pdf.getPage(1).then((page) => { const viewport = page.getViewport({ scale: 1 }) const canvas = document.createElement('canvas') const canvasContext = canvas.getContext('2d') canvas.height = viewport.height canvas.width = viewport.width const renderContext = { canvasContext, viewport, } const renderTask = page.render(renderContext) renderTask.promise.then(() => { const url = canvas.toDataURL() resolve(url) }) }) }).catch((error) => { reject(error) }) }) } ``` 4. 调用该方法并将预览URL绑定到Vue组件中的img标签: ``` <template> <div> <img :src="previewUrl" /> </div> </template> <script> import pdfjsLib from 'pdfjs-dist' export default { data() { return { pdfData: null, previewUrl: null, } }, methods: { async loadPdf() { // 加载PDF文件 this.pdfData = await this.loadPdfData() // 将PDF文件换为预览URL this.previewUrl = await this.previewPdf(this.pdfData) }, loadPdfData() { return new Promise((resolve, reject) => { // 加载PDF文件 pdfjsLib.getDocument('https://example.com/myfile.pdf').then((pdf) => { pdf.getData().then((pdfData) => { resolve(pdfData) }) }).catch((error) => { reject(error) }) }) }, previewPdf(pdfData) { // PDF文件预览URL }, }, } </script> ``` 以上是一个基本的Vue组件,用于在线预览PDF文件。您可以根据自己的需要进行修改和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值