预览 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项目中实现类似的功能,提升应用的用户体验。希望本文对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/903991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

web前端多媒体标签设置(图片,视频,音频)以及图片热区(usemap)的设置

多媒体标签运用 在HTML中有以下常见多媒体标签&#xff1a; <img> &#xff08;图像标签&#xff09; - 作用&#xff1a;用于在网页中嵌入图像。 - 示例&#xff1a; <img src"image.jpg" alt"这是一张图片"> 。其中 src 属性指定图像的…

结合无监督表示学习与伪标签监督的自蒸馏方法,用于稀有疾病影像表型分类的分散感知失衡校正|文献速递-基于生成模型的数据增强与疾病监测应用

Title 题目 Hybrid unsupervised representation learning and pseudo-label supervisedself-distillation for rare disease imaging phenotype classification with dispersion-aware imbalance correction 结合无监督表示学习与伪标签监督的自蒸馏方法&#xff0c;用于稀…

【C++】入门C++

1.C的第一个程序 之前写的C语言文件都是后缀为.c的文件&#xff0c;进入C后就要把后缀改为.c了&#xff0c;vs编译器看到是.cpp就会调⽤C编译器编译。C兼容C语言的绝大多数语法&#xff0c;所以C语言的 hallo word 依旧可以在C下使用。 //test.cpp //c语言的hallo world #inc…

紫光同创——盘古 50KN 网口板

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 一、开发系统介绍 盘古 50KN 网口板开发板&#xff08;MES50H-Ethernet&#xff09;采用了核心板扩展板的结 构&#…

本篇文章来介绍下dockerfile

我开始玩儿docker的时候&#xff0c;都是通过docker pull命令把基础镜像拉取到本地&#xff0c;然后在跑成容器&#xff0c;在操作容器&#xff0c;做一些自己的事情&#xff0c;比如安装个java环境什么的&#xff0c;直到我接触到了dockerfile&#xff0c;我发现dockerfile真是…

一款基于.NET8开源且免费的中小型酒店管理系统

项目介绍 TopskyHotelManagerSystem是一款基于.NET8开源、免费&#xff08;MIT License&#xff09;的中小型酒店管理系统&#xff0c;为中小型酒店提供全面的酒店管理系统解决方案&#xff0c;帮助酒店提高运营效率&#xff0c;优化客户体验。 开发目的 在现如今发展迅速的酒…

【本科毕业设计】基于单片机的智能家居防火防盗报警系统

基于单片机的智能家居防火防盗报警系统 源码下载摘要Abstract第1章 绪论1.1课题的背景1.2 研究的目的和意义 第2章 系统总体方案设计2.1 设计要求2.2 方案选择和论证2.2.1 单片机的选择2.2.2 显示方案的选择 第3章 系统硬件设计3.1 整体方案设计3.1.1 系统概述3.1.2 系统框图 3…

【测试平台】打包 子节点ios环境配置

主要记录如何配置ios打包机环境&#xff0c;ios环境相对来说比较简单的&#xff0c;研发配置好证书可以本地打包&#xff0c;接入流程比较简单了。 打包机系统升级 1.升级mac OS系统 一般升级好几个小时&#xff0c;可以晚上下载好 2.下载xcode并安装 Appstroe 下载安装xco…

分布式光伏是什么意思?如何高效管理?

分布式光伏系统是指在用户现场或靠近用电现场配置较小的光伏发电供电系统&#xff0c;以满足特定用户的需求。根据通知&#xff0c;分布式光伏系统主要有以下几类定义&#xff1a; 10kV以下电压等级接入&#xff0c;且单个并网点总装机容量不超过6MW的分布式电源&#xff1a;这…

初识WebGL

思路&#xff1a; 构建<canvas>画布节点&#xff0c;获取其的实例。使用getWebGLContext() 拿到画布上下文。拿到上下文用clearColor() 设置背景颜色。最后清空canvas画布,是为了清除颜色缓冲区。 html结构&#xff1a; <!DOCTYPE html> <html lang"en&…

微信小程序时间弹窗——年月日时分

需求 1、默认当前时间2、选择时间弹窗限制最大值、最小值3、每次弹起更新最大值为当前时间&#xff0c;默认值为上次选中时间4、 minDate: new Date(2023, 10, 1).getTime(),也可以传入时间字符串new Date(2023-10-1 12:22).getTime() html <view class"flex bb ptb…

redis部署手册

文章目录 一、 环境配置资源配置操作系统资源配置服务器1服务器2服务器3 目录规划 二、Redis软件部署2.1 上传相关软件包2.2 安装软件2.3 修改配置文件2.3.1 修改redis.conf2.3.2 修改sentinel.conf2.3.3 启动2.3.4 安装完成 三、Redis的哨兵恢复3.1 现象3.2 解决方法 一、 环境…

SD-WAN分布式组网:构建高效、灵活的企业网络架构

随着企业数字化转型的深入&#xff0c;分布式组网逐渐成为企业网络架构中的核心需求。无论是跨区域的分支机构互联&#xff0c;还是企业与云服务的连接&#xff0c;如何在不同区域实现高效、低延迟的网络传输&#xff0c;已成为业务成功的关键。SD-WAN&#xff08;软件定义广域…

#PCIE#基础知识分解之 CC/SRNS/SRIS 时钟架构

参考资料为PCIe Base Spec和CEM Spec。 1.1 时钟架构分类 PCIe参考时钟的三种架构&#xff1a; Common Refclk (Shared Refclk) ArchitectureData Clocked Rx ArchitectureSeparate Refclk Architecture 下面&#xff0c;我们来简单地聊一聊前面说到的三种参考时钟架构&…

开源一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码

大家好&#xff0c;我是一颗甜苞谷&#xff0c;今天分享一款前后端分离的企业级网站内容管理系统&#xff0c;支持站群管理、多平台静态化&#xff0c;多语言、全文检索的源码。 前言 在当今的数字化时代&#xff0c;企业网站和个人博客已成为信息传播和品牌建设的重要渠道。…

Linux系统基础-多线程超详细讲解(2)_线程控制

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux系统基础-多线程超详细讲解(2)_线程控制 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f4…

「C/C++」C/C++ 之 判断语句

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

2024年10月HarmonyOS应用开发者基础认证全新题库

注意事项&#xff1a;切记在考试之外的设备上打开题库进行搜索&#xff0c;防止切屏三次考试自动结束&#xff0c;题目是乱序&#xff0c;每次考试&#xff0c;选项的顺序都不同 这是基础认证题库&#xff0c;不是高级认证题库注意看清楚标题 高级认证题库地址&#xff1a;20…

go语言进阶之并发基础

并发 什么是并发&#xff0c;也就是我们常说的多线程&#xff0c;多个程序同时执行。 并发的基础 线程和进程 进程 进程是操作系统中一个重要的概念&#xff0c;指的是一个正在运行的程序的实例。它包含程序代码、当前活动的状态、变量、程序计数器和内存等资源。进程是系…

迷你航拍高清智能无人机技术详解

迷你航拍高清智能无人机技术是一种结合了高清影像拍摄、智能控制、稳定悬停以及便携性等特点的无人机技术。以下是对该技术的详细解析&#xff1a; 一、技术特点 1. 高清影像拍摄&#xff1a; 高分辨率传感器&#xff1a;迷你航拍无人机通常搭载高分辨率的相机传感器&#xf…