前景:默认情况,实现打印需要根据预览的内容进行打印。
但是当只有打印按钮存在,不预览文件内容的情况下,实现打印的话,可以通过后端接口返回服务器上PDF的地址,前端通过隐藏的iframe标签中src可实现预览功能
主要是根据pdf的链接地址实现打印pdf
实现方式1:通过fetch()将PDF地址转化为blob
print(row) {
let contractUrl = "http://xxxxxx.pdf"
fetch(contractUrl).then(res => {
return res.blob() //将url地址转化为blob
}).then(res => {
var iframe = document.createElement('iframe')
iframe.style.frameborder = 'no'
iframe.style.display = 'none'
iframe.style.pageBreakBefore = 'always'
iframe.setAttribute('id', `printPdf${row.pk}`) //id要是唯一的,不然会获取到上一个PDF文件的内容
iframe.setAttribute('name', `printPdf${row.pk}`)
iframe.src = window.URL.createObjectURL(res) //创建一个包含指定对象的URL
document.body.appendChild(iframe)
this.doPrint(`printPdf${row.pk}`)
window.URL.revokeObjectURL(iframe.src) //释放url
})
},
doPrint(val) {
var ordonnance = document.getElementById(val).contentWindow
setTimeout(() => {
ordonnance.print()
}, 500)
},
后端返回的数据是文档流的情况下
实现方式2:采用文档流的形式解决跨域的问题【不使用】
缺陷:在没有文件页面的情况下,这种打开打印窗口的方式会存在文件缓存的问题,就是在pdf文件内容修改后,打印窗口不是最新的文件内容。
print() {
// res为接口获取到的pdf文档流数据
const blob = new Blob([res], {
type: 'application/pdf'
})
var iframe = document.createElement('iframe')
iframe.style.frameborder = 'no'
iframe.style.display = 'none'
iframe.style.pageBreakBefore = 'always'
iframe.setAttribute('id', 'printPdf')
iframe.setAttribute('name', 'printPdf')
iframe.src = window.URL.createObjectURL(blob) //创建一个包含指定对象的URL
document.body.appendChild(iframe)
this.doPrint('printPdf')
window.URL.revokeObjectURL(iframe.src) //释放url
},
doPrint(val) {
var ordonnance = document.getElementById(val).contentWindow
setTimeout(() => {
ordonnance.print()
}, 500)
},
实现方式2补充:接口返回pdf文档流进行打印实现方式【可使用】
这种方式可以保证打印窗口每次预览的文件都是最新的
async print() {
// res为接口获取到的pdf文档流数据
const blob = new Blob([res], {
type: 'application/pdf'
})
let iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = window.URL.createObjectURL(blob); //创建一个包含指定对象的URL
document.body.appendChild(iframe);
// 打开打印对话框
iframe.contentWindow.focus();
iframe.contentWindow.print();
window.URL.revokeObjectURL(iframe.src); //释放url
},
实现方式3:打印pdf并且可以调整样式(比如边距)
点击打印按钮,直接打印pdf文档的情况下,会存在不同浏览器的文档打印出来的边框距离不一样的情况。
在浏览器上执行打印PDF文件时,不能调整边距,而选择打印图片格式的文件时可以调整边距。所以可以尝试把文件格式改为图片格式来直接打印。
使用
window.print()
打印的时候,@media print
只能改web网页上的内容,比如canvas,html标签等
实现流程:利用pdfjs-dist
将pdf
文件流转换成canvas
,然后将canvas
转成img
的src
地址格式,再利用print-js
直接打印图片,并且修改样式
使用的安装包版本
"pdfjs-dist": "2.6.347",
"print-js": "^1.6.0",
实现方法
<button @click="loadPdfData">打印</button>
<script>
import api from "@/api"; // 修改成自己的接口api
import printJS from "print-js";
export default {
data() {
return {
};
},
methods: {
// 获取pdf的文档流数据
getPdfUrl() {
return api.getPdfFile(; // 修改成自己的接口api
},
async loadPdfData() {
const res = await this.getPdfUrl(); // res是pdf文档流
// 拿到文档流数据
const blob = new Blob([res.data], {
type: "application/pdf",
});
let url = window.URL.createObjectURL(blob);
const pdfjs = await import("pdfjs-dist/build/pdf.js");
const pdfjsWorker = await import("pdfjs-dist/build/pdf.worker.entry");
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
//读取pdf流文件 加载PDF文档
const loadingTask = pdfjs.getDocument(url);
const pdf = await loadingTask.promise;
const numPages = pdf.numPages;
const canvasList = [];
// 遍历每一页并将其渲染到 canvas 上,转成图片
for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
// 获取pdf页
const page = await pdf.getPage(pageNumber);
// 设置缩放比例,可根据需要调整
const scale = 6;
// 获取页的尺寸
const viewport = page.getViewport({ scale });
// 创建 canvas 元素
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
// 设置canvas的尺寸
canvas.height = viewport.height;
canvas.width = viewport.width;
// 将pdf页渲染到canvas上
const renderContext = {
canvasContext: context,
viewport: viewport
};
await page.render(renderContext).promise;
canvasList.push(canvas);
}
// 将 canvas 转换为图片的 DataURL 数组
const imageUrls = canvasList.map(canvas => canvas.toDataURL('image/png'));
if (!imageUrls.length) {
this.$conforms({
title: "提示",
content: "文件获取失败,请重新打印!",
rightBtnText: "关闭",
rightBtn: () => {},
});
return;
}
// 使用 print-js 打印图片
printJS({
printable: imageUrls,
type: 'image',
style:
"@media print{ @page { size: A4; margin: 20px; mso-header: none; mso-footer: none; } body{margin: 0px}}",
}); // 修改打印窗口的边距样式等
},
},
};
</script>
// 解释:scale可以设置图片的清晰度问题,值越大越清晰,但是图片也会越大
const viewport = page.getViewport({ scale: 6 });
说明:
使用的@page
是一种 CSS 规则,用于修改打印页面的不同方面。它的目标是修改页面的尺寸、方向和页边距。
@page {size: A4;margin: 0; mso-header:none: none; ;mso-footer·: none;}
size
: 打印纸大小
margin
:打印区域外边距
mso-header
:设置页头
mso-footer
:设置页脚
body{margin:0px}
图片外边距,设置上下均为0 可以去掉空白的首页和尾页
注意:打印窗口的设置不同,会导致出现不一样的内容, 比如linux系统和windows系统,预览出来的pdf可能会出现字体不一致。比如勾选了页眉和页脚,右下角会出现多余的符号/
实现方式4
后端接口直接返回图片文件流,利用print-js
进行打印
// res为服务端返回的数据流,图片格式
let data = new Blob([res]);
let file = new Blob([data]);
let objectUrl = window.URL.createObjectURL(file);
printJS({
printable: objectUrl,
type: "image",
});