当前位置: 首页>編程日記>正文

html使用iframe包含pdf文件,react项目利用iframe显示pdf文件并打印

html使用iframe包含pdf文件,react项目利用iframe显示pdf文件并打印

描述:

最近项目有个需求,需要在页面上显示pdf文件,经过多次尝试,终于以较好的效果完成,特此做此记录,需求:

需要在前端页面上弹窗显示预览pdf文件

只打印pdf内容

接口需要用post请求json格式传参,后端接口根据情况返回不同的数据,正常情况会返回pdf的文件流,特殊情况会返回json字符串,显示报错信息。

显示pdf

页面显示pdf有几种方法,最简单的就是设置iframe标签的src地址为pdf资源url:

但是这种方式,只适合pdfUrl接口为get方式,不支持post请求传参,更不用说传json了。

使用 react-pdf 等第三方插件, 使用第三方的插件还要去熟悉相应的api和引入比较大的包,所以个人没用这个方案了。

最终还是用原生的iframe标签实现需求,具体原理就是iframe标签的src属性除了可以接收url地址,也可以接收base64格式编码,以及URL.createObjectURL()方法生成的地址。

fetch的坑

定好显示方案后,接下来的工作就是请求接口,获取文件流,然后赋值给src属性。项目框架使用的是fetch请求。

第一个坑:fetch请求返回的body为ReadableStream对象,因此fetch请求成功返回的response并不是真实的数据,需要使用相应的方法进行解析,才能拿到真实的数据。

转自MDN的fetch-body解释:ea2cf39cd3978f65696e7ce01727ae10.png

进行blob解析后,接下来我们就可以使用FileReader对象的readAsDataURL方法将blob文件流转为URL格式的字符串(base64编码),然后就可以将这个字符串赋值给src属性了。

转自MDN的FileReader.readAsDataURL()解释:

readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

直接上代码,大概就能了解整个流程了:

fetch('http://www.lswz.gov.cn/html/ndbg/2019-03/28/243933/files/8cc8f0c824e74e3dbc06ac3e74355def.pdf')

.then( res => res.blob()) // 解析res值为blob

.then( response => {

const reader = new FileReader();

// 这里转换是异步的

reader.readAsDataURL(response);

// 绑定this

const that = this;

// 监听转换是否成功

reader.addEventListener("loadend", function() {

// reader.result 结果赋值给iframe的src属性

that.setState({

iframeSrc: reader.result

})

});

})

复制代码

打印pdf内容

现在显示已经没问题了,但是打印却又有另外一个坑了。

我使用的方法为调用原生的window对象window.print()方法,通过获取iframe窗口的window对象,调用该方法就可以调起游览器的打印窗口,进行打印,然而想象很美好,结果游览器报错:Uncaught DOMException: Blocked a frame with origin "http://localhost:3000" from accessing a cross-origin frame.

原来是出现跨域问题了,因为此时的iframe标签的src属性值为:"data:application/pdf;base64,...." 这么一串字符串,因为iframe的同源策略,父窗口是不能调用子窗口的所有方法和属性的。因此要想打印,只能另寻他法。

这里我们就可以用另外一个方法,调用 URL.createObjectURL() 方法会生成一个地址,这个地址代表着根据 blob 对象生成的资源入口,而这个资源入口存放于浏览器维护的一个 blob URL store 中。

生成的 URL 大概都长这样:

其中的网址和网页的网址上一致的,这时就解决跨域问题了,我们可以愉快的调用子窗口的pint()方法了。

代码:

fetch('http://www.lswz.gov.cn/html/ndbg/2019-03/28/243933/files/8cc8f0c824e74e3dbc06ac3e74355def.pdf')

.then( res => res.blob()) // 解析res值为blob

.then( response => {

const url = URL.createObjectURL(response);

this.setState({

htmlStr: url

})

})

复制代码

可以看到代码也简洁了很多,不用增加监听转化是否完成。

至此整个需求的功能开发也到此完成了。

总结

总结这次开发,可以说是基础不牢,广度不够,不了解js的各种编码方法和原理,然后在网上花费了大量时间去找解决方案,结果都不如意,不过做开发就是这样,需要自己去不断的踩坑,找到方案快速试错。

最后上个效果图:5de7ee61143930b864a7a5d8743632f5.png

参考链接


https://www.fengoutiyan.com/post/13481.html

相关文章:

  • react怎么编译成HTML的
  • html中iframe用法
  • react现在html转pdf
  • react引用html5
  • jquery pdf
  • react导出pdf
  • 获取iframe页面内容
  • canvas pdf
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機