当前位置: 首页 > article >正文

预览 PDF 文档

引言

在现代Web应用中,文件预览功能是非常常见的需求之一。特别是在企业级应用中,用户经常需要查看各种类型的文件,如 PDF、Word、Excel 等。本文将详细介绍如何在Vue项目中实现 PDF 文档的预览功能。

实现原理

后端API

后端需要提供一个API接口,用于获取文件的二进制数据。这个接口通常会根据文件名或文件ID来返回文件内容。

前端处理

前端通过调用后端 API 获取文件的二进制数据,并将其转换为 Blob 对象。然后使用window.URL.createObjectURL 方法生成一个临时的 URL,最后通过 window.open 方法在新窗口中打开这个 URL,从而实现文件预览。

代码示例

node 服务端代码

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');

const app = express();
// 定义文件夹路径
const mergedDir = path.join(__dirname, 'merged');

// 文件下载接口
app.get('/download', (req, res) => {
    const { fileName } = req.query;
    const filePath = path.join(mergedDir, fileName);

    fs.access(filePath, fs.constants.F_OK, (err) => {
        if (err) {
            return res.status(404).json({ error: '文件不存在' });
        }

        const stats = fs.statSync(filePath);

        if (stats.isFile()) {
            const contentType = getContentType(fileName);
            res.setHeader('Content-Type', contentType);
            // 对 fileName 进行编码
            const encodedFileName = encodeURIComponent(fileName);
            res.setHeader('Content-Disposition', `attachment; filename=${encodedFileName}`);
            fs.createReadStream(filePath).pipe(res);
        } else {
            res.status(400).json({ error: '不是一个文件' });
        }
    });
});

// 获取文件的 MIME 类型
function getContentType(fileName) {
    const ext = path.extname(fileName).toLowerCase();
    switch (ext) {
        case '.js':
            return 'application/javascript';
        case '.json':
            return 'application/json';
        case '.html':
            return 'text/html';
        case '.css':
            return 'text/css';
        case '.txt':
            return 'text/plain';
        case '.png':
            return 'image/png';
        case '.jpg':
        case '.jpeg':
            return 'image/jpeg';
        case '.gif':
            return 'image/gif';
        case '.pdf':
            return 'application/pdf';
        case '.doc':
            return 'application/msword';
        case '.docx':
            return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
        case '.ppt':
            return 'application/vnd.ms-powerpoint';
        case '.pptx':
            return 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
        case '.xlsx':
            return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        default:
            return 'application/octet-stream';
    }
}
// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

前端代码实现

接口 API

import request from "@/utils/request";

// 获取文件列表
export function getFilesList() {
  return request({
    url: "/getFilesList",
    method: "get",
  });
}

// 文件预览
export function previewFile(fileName) {
  return request({
    url: `/download?fileName=${fileName}`,
    method: "get",
    responseType: "blob",
  });
}

页面代码

<template>
  <div class="table">
    <el-table :data="tableData" header-align="center" border style="width: 100%">
      <el-table-column align="center" type="index" width="60" label="序号">
      </el-table-column>
      <el-table-column align="center" prop="fileName" label="文件名" />
      <el-table-column align="center" prop="upTime" label="上传日期" width="200" />
      <el-table-column align="center" fixed="right" label="操作" width="120">
        <template slot-scope="scope">
          <el-button @click="handleClick(scope.row)" type="text">预览</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import { previewFile } from "@/api/file";
import { timeStampToString } from "@/utils/utils";
import { getFilesList } from "@/api/file";

export default {
  name: "fileTable",
  data() {
    return {
      tableData: [],
    }
  },
  created() {
    this.getFileName();
  },
  methods: {
    // 获取文件列表
    async getFileName() {
      const { code, data: resData } = await getFilesList();
      console.log('code, data::: ', code, resData);
      if (code === 200) {
        resData.forEach(item => {
          item.upTime = timeStampToString(item.upTime);
        });
        this.tableData = resData;
      }
    },
    handleBlob(blob, filename) {
      console.log('blob::: ', blob,filename);
      let url = window.URL.createObjectURL(blob);
      var tempwindow = window.open("_blank");
      if (tempwindow) {
        tempwindow.location = url;
      }
    },
    // 文件预览
    async handleClick(row) {
      try {
        const response = await previewFile(row.fileName)
        console.log('response::: ', response);
        this.handleBlob(response, row.fileName)
      } catch (err) {
        console.error('Failed to preview file', err);
      }
    },
  }
}
</script>

实现效果
在这里插入图片描述

设置网页标题为文件名

 handleBlob(blob, filename) {
      console.log('blob::: ', blob, filename);
      let url = window.URL.createObjectURL(blob);

      // 创建一个新窗口
      let tempWindow = window.open("", "_blank");

      // 设置新窗口的标题为文件名
      tempWindow.document.title = filename;

      // 在新窗口中嵌入一个 <iframe> 来预览 PDF 文件
      tempWindow.document.write('<html><head><title>' + filename + '</title></head><body>');
      tempWindow.document.write('<iframe src="' + url + '" style="width:100%;height:100%;border:none;"></iframe>');
      tempWindow.document.write('</body></html>');

      // 确保新窗口的内容加载完成后再释放 URL
      tempWindow.onload = function () {
        window.URL.revokeObjectURL(url);
      };
    },

修改后的效果
在这里插入图片描述

总结

本文详细介绍了如何在Vue项目中实现PDF文档的预览功能。通过前后端的协同工作,我们实现了从文件的存储、获取到预览的完整流程。具体来说:

  • 后端API:提供了文件下载接口,根据文件名或文件ID返回文件的二进制数据,并设置了正确的MIME类型。

  • 前端处理:通过调用后端API获取文件的二进制数据,将其转换为 Blob 对象,并生成一个临时的 URL。然后在新窗口中打开这个 URL,实现文件预览。

  • 优化体验:为了提升用户体验,我们进一步优化了预览功能,通过在新窗口中嵌入 <iframe> 并设置网页标题为文件名,使得预览界面更加友好和直观。

通过本文的介绍,读者可以轻松地在自己的Vue项目中实现类似的功能,提升应用的用户体验。希望本文对大家有所帮助。


http://www.kler.cn/a/371481.html

相关文章:

  • 如何选择适合自己的 Python IDE
  • fmql之Linux以太网
  • 2024网鼎杯青龙组初赛 web2
  • 一道巧妙的卡特兰数建模
  • Android -- 调用系统相册之图片裁剪保存
  • C#版的有道智云对话接口
  • android 手机姿态(2)
  • scenedetect视频场景变换侦测与分割
  • Me 攒的GPT修改论文提示词
  • Unity GameFramework Star Force 拆解(一)—— 启动流程
  • 机器学习与神经网络:诺贝尔物理学奖的新方向
  • Gradle 配置后续一致更新
  • redis的三种客户端
  • SpringMVC学习(2)
  • Mac开发环境配置- Shell/Homebrew/ruby
  • ele-table表格列表内,双击编辑部分信息(el-table组件同理)
  • C# OpenCvSharp DNN UNet 推理
  • 华为手机系统应用瘦身
  • 了解桌面机床用于学校教学培训应用-桌面级CNC机床
  • Debug日程工作经验总结日程常用
  • 五指cms安装
  • ubuntu20.04系统安装
  • 使用Python和OpenCV实现火焰检测
  • c++ assert
  • [机器学习]集成学习
  • Docker架构