软件教程 2025年08月6日
0 收藏 0 点赞 857 浏览 5616 个字
摘要 :

文章目录 一、实现思路 二、前端实现方式 2.1 使用Blob实现PDF下载预览 2.2 使用JSON格式实现PDF下载预览 三、后端实现代码 四、使用pdfjs转换为canvas渲染PDF 今天……




  • 一、实现思路
  • 二、前端实现方式
    • 2.1 使用Blob实现PDF下载预览
    • 2.2 使用JSON格式实现PDF下载预览
  • 三、后端实现代码
  • 四、使用pdfjs转换为canvas渲染PDF

今天来给大伙分享一下前端Vue结合后端Node.js实现PDF下载和预览功能的具体方法。先给大伙看看最终实现的效果:有一个记录了不同版本更新信息的表格,里面包含版本号、更新内容、负责人和更新时间等信息。在实际应用场景里,这个表格数据可能就存放在PDF文件中,咱们要做的就是实现对这个PDF的下载和预览。前端Vue+后端Node.js实现PDF下载和预览功能

一、实现思路

整体实现思路是这样的:前端借助pdfjs来渲染PDF文件;后端负责读取PDF文件,并把它转换为流文件,之后通过接口响应发送给前端,前端收到数据后进行渲染展示。

二、前端实现方式

前端从服务端获取流文件有JSON和Blob两种形式,这两种方式各有优劣。JSON返回的数据字段更灵活,开发者能根据不同的业务情况进行针对性处理;Blob形式则相对简单直接,后端返回的数据会被整合成一个Blob类型的数据对象。

2.1 使用Blob实现PDF下载预览

采用Blob形式时,需要把接口的返回类型responseType设置为Blob。这种方式会将后端返回的所有数据打包成一个Blob类型的数据。这里简单解释一下Blob,它是一种二进制大对象,在处理文件数据时经常会用到。下面看看具体代码:

// 创建下载链接的函数,接收文件数据buffer和文件名filename(默认为\'可回溯.pdf\')
const createLinkDownload = (buffer, filename = \'可回溯.pdf\') => {
    // 根据文件数据创建Blob对象,指定类型为\'application/pdf\'
    const blob = new Blob([buffer], { type: \'application/pdf\' });
    // 创建一个a标签用于触发下载
    const link = document.createElement(\'a\');
    // 为a标签设置下载链接,通过URL.createObjectURL将Blob对象转换为可访问的URL
    link.href = URL.createObjectURL(blob);
    // 设置下载的文件名
    link.download = filename;
    // 模拟点击a标签,触发下载操作
    link.click();
};

// 执行Blob下载的函数
const blobDownload = async () => {
    // 发送axios的get请求到\'/api/download\'接口,设置responseType为\'blob\'
    const response = await axios.get(\'/api/download\', {
        responseType: \'blob\', 
    });
    // 调用createLinkDownload函数,传入响应数据进行下载
    createLinkDownload(response.data);
};

再看看服务端的接口逻辑,这里用的是Node.js和Express框架:前端Vue+后端Node.js实现PDF下载和预览功能

从上面的代码可以看出,当使用Blob形式时,前端请求接口后,即便服务端返回了加载成功等信息,前端也获取不到这些字段,因为请求时设置了responseType: \'blob\',而不是application/json前端Vue+后端Node.js实现PDF下载和预览功能

2.2 使用JSON格式实现PDF下载预览

使用JSON格式的关键在于,后端要把读取到的PDF文件转换为base64编码。由于base64本质是字符串,和Blob不同,前端获取到数据后,需要将base64转换为Buffer才能进一步处理。JSON格式的优势在于能更明确地返回字段,数据结构更清晰。前端Vue+后端Node.js实现PDF下载和预览功能下面是具体实现代码:

// 创建下载链接的函数,和Blob方式中的这个函数作用相同
const createLinkDownload = (buffer, filename = \'可回溯.pdf\') => {
    const blob = new Blob([buffer], { type: \'application/pdf\' });
    const link = document.createElement(\'a\');
    link.href = URL.createObjectURL(blob);
    link.download = filename;
    link.click()、、、、;
};

// 执行JSON下载的函数
const jsonDownload = async () => {
    // 发送axios的post请求到\'/api/download\'接口
    const response = await axios.post(\'/api/download\', {});
    // 打印响应数据,方便调试查看
    console.log(\'response\', response);
    // 将base64编码的数据转换为ArrayBuffer
    const arrerBuffer = base64ToBytes(response.data.data);
    // 调用createLinkDownload函数,传入转换后的ArrayBuffer进行下载
    createLinkDownload(arrerBuffer);
};

三、后端实现代码

后端代码和前面Blob方式中处理下载接口的代码基本一致,主要是通过Express框架设置接口,读取PDF文件并进行相应处理。代码如下:

// 引入express框架
const expressApp = require(\'express\')
// 用于处理文件路径
const path = require(\'path\')
// 用于异步操作文件系统
const fs = require(\'fs/promises\')
// 自定义的通用响应处理函数
const { commonResponse } = require(\'./common\')
// 创建express应用实例
const app = expressApp()
// 设置服务端口
const port = 8085
// 定义一个函数,用于解析相对路径为绝对路径
const resolveDir = (fileDir) => path.resolve(__dirname, fileDir)
// 指定要下载的PDF文件路径
const pdfDir = resolveDir(\'../assets/pdf/可回溯逻辑梳理.pdf\')

// 处理GET请求的下载接口
app.get(\'/download\', (req, res) => {
    // 使用res.download方法直接下载指定路径的PDF文件,并命名为\'可回溯pdf\'
    res.download(pdfDir, \'可回溯pdf\')
    // 发送通用响应,告知前端加载成功
    res.send(commonResponse(\'加载成功\', \'1\', {}))
})

// 处理POST请求的下载接口
app.post(\'/download\', async (req, res) => {
    // 以base64编码方式读取PDF文件内容
    const pdfStream = await fs.readFile(pdfDir, { encoding: \'base64\' })
    // 如果读取失败,返回加载失败的响应
    if (!pdfStream) {
        return res.send(commonResponse(\'加载失败\', \'-2\', {}))
    }
    // 读取成功则返回加载成功的响应,包含读取的PDF文件内容
    res.send(commonResponse(\'加载成功\', \'1\', pdfStream))
})

// 启动服务,监听指定端口
app.listen(port, () => {
    console.log(\"服务启动成功\", port)
})

四、使用pdfjs转换为canvas渲染PDF

在实现PDF预览时,使用pdfjs将PDF转换为canvas进行渲染。这里的核心要点是如何让PDF显示得更清晰,关键就在于对PDF进行缩放,使其适配屏幕大小。下面这段代码详细展示了实现过程:

// 渲染PDF页面的函数,接收要渲染的页码pageNumber
const renderPdfPage = async (pageNumber) => {
    // 获取指定页码的页面
    const page = await pdfDocumentInstance.getPage(pageNumber);
    // 打印页面信息,方便调试查看
    console.log(\'page\', page);

    // 获取设备像素比,用于适配不同屏幕分辨率
    const dpr = window.devicePixelRatio || 1;
    // 获取设备的实际宽度
    const deviceWidth = window.innerWidth || 414;

    // 计算rem基准值,这里设定1rem = 100px
    const remBase = 100;

    // 获取原始的viewport,用于计算合适的缩放比例
    const originalViewport = page.getViewport({ scale: 1.0 });
    // 根据设备宽度和原始viewport宽度计算适合屏幕的缩放比例
    const fitScale = (deviceWidth * dpr) / originalViewport.width;
    // 设置一个更高的基础缩放比例,用于提高清晰度
    const qualityScale = 2.5;

    // 根据计算的缩放比例获取新的viewport,用于设置画布尺寸
    const viewport = page.getViewport({ scale: fitScale * qualityScale });
    // 获取用于渲染PDF的canvas元素
    const canvasEls = pdfCanvas.value[pageNumber - 1];
    // 获取canvas的2d绘图上下文
    const context = canvasEls.getContext(\'2d\', { alpha: false });

    // 设置canvas的实际高度和宽度,考虑缩放比例
    canvasEls.height = viewport.height;
    canvasEls.width = viewport.width;

    // 设置canvas的显示高度和宽度,使用rem单位,方便适配不同屏幕
    canvasEls.style.height = `${viewport.height / (dpr * qualityScale) / remBase}rem`;
    canvasEls.style.width = `${viewport.width / (dpr * qualityScale) / remBase}rem`;

    // 启用图像平滑处理,提高渲染质量
    context.imageSmoothingEnabled = true;
    context.imageSmoothingQuality = \'high\';

    // 根据设备像素比和质量缩放来调整上下文
    context.scale(1, 1);

    // 定义渲染上下文对象,包含canvas绘图上下文和viewport信息
    const renderContext = {
        canvasContext: context,
        viewport: viewport,
    };
    // 渲染页面,并等待渲染完成
    await page.render(renderContext).promise;
    // 如果还有更多页面需要渲染,递归调用渲染下一页
    if (maxRenderPdfNum.value > pageNumber) {
        renderPdfPage(pageNumber + 1);
    }
};

// 获取PDF文件数据的函数
const getPdf = async () => {
    // 打印日志,方便调试查看
    console.log(\'1111\');
    // 发送请求获取PDF文件流
    const response = await getPdfFileStream();
    // 打印响应数据,方便调试查看
    console.log(\'response\', response);
    // 如果响应存在且数据中的STATUS字段为\'1\',说明获取数据成功
    if (response && response.data?.STATUS === \'1\') {
        // 将获取到的PDF数据存储到响应式变量pdfBufferData中
        pdfBufferData.value = response.data.data;
    }
};

// 组件挂载完成后的生命周期钩子函数
onMounted(async () => {
    // 设置pdfjs的worker源,确保其能正常工作
    new pdfjsLib.GlobalWorkerOptions().workerSrc = pdfjsWorker || {};
    // 发送请求获取PDF文件数据
    await getPdf();

    // 将base64编码的PDF数据转换为ArrayBuffer
    const arrayBuffer = await base64ToBytes(pdfBufferData.value);

    // 使用pdfjsLib加载PDF文件数据
    const loadingTask = pdfjsLib.getDocument({ data: arrayBuffer });

    // 等待PDF文档加载完成
    pdfDocumentInstance = await loadingTask.promise; 
    // 获取PDF文档的总页数并存储到响应式变量maxRenderPdfNum中
    maxRenderPdfNum.value = pdfDocumentInstance._pdfInfo.numPages; 
    // 开始渲染第一页
    renderPdfPage(1);
});

以上就是前端Vue结合后端Node.js实现PDF下载和预览功能的全部内容啦!在实际开发过程中,大家可以根据具体的业务需求对代码进行调整和优化。要是在实现过程中遇到什么问题,欢迎在评论区留言交流!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6824.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号