关于Pdf.js的基础知识,请参考我的博客 

上面两篇博客中介绍的内容都是基于直接加载远程服务器中静态PDF文件(即URL地址)来渲染PDF的,实际业务场景中,如与第三方系统对接过程中,第三方系统不直接公开PDF的URL地址,而是通过接口提供PDF文件流,这种方式处理起来就相对麻烦一点。本篇文章详细介绍使用Pdf.js插件通过读取pdf文件流的方式来渲染PDF文件。

先看效果

点击按钮打开PDF渲染页面

下面介绍实现的完整流程

第1步:编写WebAPI接口,返回PDF文件流
假设pdf文件在服务器的D盘测试目录下,通过File.OpenRead()方法读取并返回pdf文件流。
 1 using Microsoft.AspNetCore.Mvc;
2
3 namespace SparkWuTong.WebApiX6.Controllers;
4
5 [ApiController]
6 [Route("api/[controller]/[action]")]
7 public class FileTestController : ControllerBase
8 {
9 [HttpGet]
10 [HttpPost]
11 public async Task<IActionResult> ReadFileStream()
12 {
13 var filePath = "D:\\测试\\发票.pdf";
14 var stream = System.IO.File.OpenRead(filePath);
15 var result = new FileStreamResult(stream, "application/octet-stream")
16 {
17 FileDownloadName = "发票.pdf" // 可选:设置下载文件名
18 };
19
20 return await Task.FromResult(result);
21 }
22 }

还有另外一种情况,读取远程服务器中PDF文件,如下示例

 1 using Microsoft.AspNetCore.Mvc;
2
3 namespace SparkWuTong.WebApiX6.Controllers;
4
5 [ApiController]
6 [Route("api/[controller]/[action]")]
7 public class FileTestController : ControllerBase
8 {
9 [HttpGet]
10 [HttpPost]
11 public async Task<IActionResult> ReadFileStream()
12 {
13 var fileUrl = "http://localhost:5600/plugins/pdf-js/test_file.pdf";
14 HttpClient client = new HttpClient();
15 var stream = await client.GetStreamAsync(fileUrl);
16
17 return new FileStreamResult(stream, "application/octet-stream")
18 {
19 FileDownloadName = "测试文件.pdf" // 可选:设置下载文件名
20 };
21 }
22 }

提示:两种读取pdf文件的方式都可以使用,具体依赖于实际应用场景。

第2步:基于jQuery ajax 封装读取接口并返回文件流的方法

jQuery是大家开发中最常用的脚本库之一,其中 ajax() 方法的能力超级强大,经常用于发送 get/post请求服务器的资源,绝大部分情况下响应格式为 application/json。如果发送请求到上述WebAPI接口是无法正常接收数据的,因为接口返回内容的是文件流。为了能够接收到文件流,这里需要做特殊的配置:

  • 核心1:(1515行)设置 mimeType 为 text/plain; charset=x-user-defined 意思是将以普通文本的格式接收 WebAPI 返回的内容(非常规的 application/json)。
  • 核心2:(1518 至 1524行)接收到 data 数据后,将其转换为 pdf.js 库中定义的 Uint8Array 类型。实现思路参考 pdf.js 中的方法。

 

  • 核心3:(1527行)利用浏览器的File对象将字节数组转换为pdf文件,类型为 application/pdf;charset-UTF-8。
  • 核心4:(1528行)为pdf文件创建一个临时访问的地址。格式为  blob:http://localhost:5600/75f4c795-52fb-4aaa-9204-9744e92649abjiang

将生成的blob地址拷贝到浏览器中访问,并不能成功。

----------------------------------------------------------------------------

URL.createObjectURL() 方法会根据传入的参数创建一个指向该参数对象的URL。这个URL的生命仅存在于它被创建的这个文档里,新的对象URL指向执行的File对象或者是Blob对象。

语法格式为

objectURL = URL.createObjectURL(blob || file);
  • 参数:

  File对象或者Blob对象

    • File对象就是一个文件,比如我用input type="file"标签来上传文件,那么里面的每个文件都是一个File对象。
    • Blob对象就是二进制数据,比如通过new Blob()创建的对象就是Blob对象。又比如,在XMLHttpRequest里,如果指定responseType为blob,那么得到的返回值也是一个blob对象。
  • 注意点:

  每次调用createObjectURL的时候,一个新的URL对象就被创建了。即使你已经为同一个文件创建过一个URL,如果你不再需要这个对象,要释放它,需要使用URL.revokeObjectURL()方法。当页面被关闭,浏览器会自动释放它,但是为了最佳性能和内存使用,当确保不再用得到它的时候,就应该释放它。

有的同学会说为什么一定要求用jQuery ajax()呢,确实还有很多其他便捷的方法来读取文件流,比如 fetch()方法就非常的简单

 1 var newPdfUrl = 'http://localhost:5610/api/FileTest/ReadFileStream';
2 fetch(newPdfUrl)
3 .then(function (response) {
4 if (response.ok) {
5 return response.arrayBuffer();
6 }
7 else {
8 spark.alertErrorX("从服务器获取pdf文件失败!");
9 }
10 })
11 .then(buffer => {
12 // TODO
13 })
14 .catch(function (err) {
15 log('------插件读取pdf文件发生异常:' + err);
16 });

还有原生的  XMLHttpRequest 对象也可以直接读取文件流

 1 var xhr = new XMLHttpRequest();
2 xhr.open('GET', pdfUrl, true);
3 xhr.responseType = 'blob';
4 xhr.onreadystatechange = function () {
5 if (xhr.readyState !== 4) {
6 return;
7 }
8
9 var status = xhr.status;
10 if ((status >= 200 && status < 300) || status === 304) {
11 // TODO
12 }
13 };
14 xhr.send();
第3步:利用 pdf.js 的 viewer.html 渲染文件

  • 12行,定义一个iframe,用于加载pdf.js中提供的示例页面 view.html。
  • 32行,将第2步中创建的blob url 赋值给  view.html 页面的 file 参数。

完成以上步骤后,在网页中即可完整的渲染pdf文件了

使用 pdf.js 通过文件流方式加载pdf文件的更多相关文章

  1. 使用 pdf.js 在网页中加载 pdf 文件

    在网页中加载并显示PDF文件是最常见的业务需求.例如以下应用场景:(1)在电商网站上购物之后,下载电子发票之前先预览发票.(2)电子商务管理系统中查看发布的公文,公文文件一般是PDF格式的文件. 目前 ...

  2. 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间

    [源码下载] 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间 作者:webabcd 介绍速战速决 之 PHP 动态地创 ...

  3. Spire.XLS,生成Excel文件、加载Excel文件

    一.组件介绍 Spire.XLS是E-iceblue开发的一套基于企业级的专业Office文档处理的组件之一,全称Spire.Office for .NET.旗下有Spire.Doc,Spire XL ...

  4. Android根据文件路径加载指定文件

    Android根据指定的文件路径加载指定文件格式(图片格式 png, gif,jpg jpeg)的文件相关信息的列表. 如图: 代码: public class Util { /**** * 计算文件 ...

  5. android--------根据文件路径加载指定文件

    Android根据指定的文件路径,加载该路径下指定文件格式(图片格式 png, gif,jpg jpeg)的文件相关信息的列表. 如图: public class MainActivity exten ...

  6. QML中文件的加载(三种方法)

    在这里小小总结一下QML文件中如何加载QML文件与JavaScript文件. 1.QML文件中加载JavaScript文件 语法: import <ModuleIdentifier> &l ...

  7. vue-cli之加载ico文件

    vue-cli之加载ico文件 vue-cli加载ico文件需要在vue.config.js设置ico加载,代码如下: module.exports = { publicPath: process.e ...

  8. dom4j加载xml文件

    ## dom4j加载xml文件 ``` // 1. 加载xml文件 InputStream is = MyTest.class.getResourceAsStream("user.xml&q ...

  9. 字节码(.class)文件的加载过程

    类加载 在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 类型可以是Class,Interface, 枚举等. Java虚拟机与程序的生命周期 在如下几种情况下,Java虚拟机 ...

  10. nginx反向代理转发后页面上的js css文件无法加载【原创】

    故障现象:nginx做代理转发后,发现页面上的js css文件无法加载,页面样式乱了. 原因:没有配置静态资源 解决js css文件无法加载无法访问的问题 解决办法: 修改配置文件nginx.conf ...

随机推荐

  1. 0.2 Afterword to the Tenth Anniversary Edition(2010)

    近十年来的进展: 1. 在实验实施领域. 超导电路:2-qubit量子算法:3-qubit 系统. 基于核自旋和单光子: 演示'量子纠错'和'量子模拟' 离子阱系统: '量子搜索算法'和'量子傅里叶变 ...

  2. 基于Java+SpringBoot心理测评心理测试系统功能实现七

    一.前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色.随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态.诊断心理问题.制定心理治疗方案的工 ...

  3. 合宙低功耗4G模组HTTP网络协议应用

    ​ 一.HTTP概述 1.1 简介 HTTP是HyperTextTransferProtocol(超文本传输协议)的缩写.HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型.HT ...

  4. golang之验证器validator

    快速安装 使用之前,我们先要获取validator这个库. # 第一次安装使用如下命令 go get github.com/go-playground/validator/v10 # 项目中引入包 i ...

  5. elastic 7.15 集群搭建

    准备三台ES 7.15 关于系统配可以参考之前的文章. https://www.cnblogs.com/yg_zhang/p/10214196.html 这里写一下 的集群配置.这里和之前配置有所不同 ...

  6. MiniTomcat 系列:第一章:解锁实现基础 HTTP 服务器的奥秘

    第一步:实现基础 HTTP 服务器 在这一章中,我们将从零开始编写一个简单的 HTTP 服务器.这个服务器的基本功能是监听一个端口,接收来自客户端的 HTTP 请求,并返回一个 HTTP 响应.我们将 ...

  7. OceanBase 的探索与实践

    作者:来自 vivo 互联网数据库团队- Xu Shaohui 本文总结了目前我们遇到的痛点问题并通过 OceanBase 的技术方案解决了这些痛点问题,完整的描述了 OceanBase 的实施落地, ...

  8. Winform在主窗体加载前弹出登录窗体

    1:主窗体代码 点击查看代码 //实例化登录窗体 FrmLogin frmLogin = new FrmLogin(); //读取登录窗体的返回结果 DialogResult dialogResult ...

  9. 推荐一款轻量级且强大的 Elasticsearch GUI : elasticvue

    推荐一款轻量级且强大的 Elasticsearch GUI : elasticvue 很多同学都是用过 Elasticsearch 的 GUI 工具 Kibana ,但 Kibana 相对比较重,这篇 ...

  10. 题解:P10704 救赎(Redemption)

    数论题,先看数据范围,发现 $n$ 和 $m$ 都非常大,但是 $\sum_{i=1}^{i=n}a_i \le 10^9$. 解以上不等式得不同的 $a_i$ 大约有 $40000$ 个.记有 $c ...