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

预览 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>');// 确保新窗口的内容加载完成后再释放 URLtempWindow.onload = function () {window.URL.revokeObjectURL(url);};},

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

总结

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

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

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

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

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


http://www.mrgr.cn/news/62474.html

相关文章:

  • 准备华为od技术面试(技术一面,技术二面),看这篇就够了
  • pip命令行安装pytest 一直报错
  • Adam 优化算法《学习笔记》
  • Spring的IOC技术(配置文件形式)
  • C语言教程——数组(2)
  • 【c语言】运算符汇总(万字解析)
  • 基于QT(C++)实现(界面)即时通讯软件
  • 语义检索系统嵌入模型选型技术方案
  • 海思MPP音视频总结
  • 【综合算法学习】(第十二篇)
  • LC946. 验证栈序列
  • 引导徒弟找到用java程序拉取钉钉考勤记录的方法
  • 最新EI会议论文投稿指南:10个热门学术会议推荐
  • Chrome浏览器音/视频无法自动播放
  • OpenCV自动滑块验证(Java版)
  • Spring Boot助力校园社团信息数字化管理
  • Python爬虫:在1688上“侦探游戏”获取店铺详情
  • 大厂面试真题-简单说说中台的架构设计
  • Python酷库之旅-第三方库Pandas(181)
  • NocoBase 本周更新汇总:提升表格区块渲染性能等
  • 炫酷!HTMLCSS 让五星评级单选按钮“活“起来
  • Spring Boot技术在校园社团管理中的高效应用
  • 微信小程序开发(教学笔记)——一、通过微信官方文档认识、学习小程序
  • 让卷积神经网络来辨识马和人
  • 三合一无线键鼠中射频芯片-PHY6233
  • clickhouse运维篇(二):多机器手动部署ck集群