一、pdf下载
1.1 需求描述
开发聚合支付系统时,遇到报表pdf文件下载(单个或多个)的需求
后端会返回pdf下载地址,若是仅一个pdf下载地址,最直接的方式就是跳转该地址,会到达一个pdf预览页面(里边包含下载操作)。但是,客户的需求是:
在当前页面提供下载按钮,分两种情况
- 一个pdf下载地址,直接导出
- 多个pdf地址,导出zip压缩包
查阅众多文章后,实现该需求,并封装成了函数。如下所示:
1.2 @/uitls/download-pdf.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import { saveAs } from 'file-saver'
import JSZip from 'jszip'
import { Notification } from 'element-ui'
/**
* 传入一个pdf下载地址,直接导出pdf
*/
type TDownloadPDFType = {
PDFUrl: string,//pdf下载地址
exportFileName: string,//导出pdf文件名称
headers?: {[propName: string]: string}//请求头[可选]
}
export const downloadPDF = (
params: TDownloadPDFType,
startCallback?: Function,
endCallback?: Function
) => {
//==============axios方式==============
// 开始回调函数
if(startCallback) {
startCallback();
}
const config: AxiosRequestConfig = {
url: params.PDFUrl,
method: 'GET',
responseType: 'blob',
}
//是否有请求头
if(params.headers) {
config.headers = params.headers;
}
axios(config).then((res: AxiosResponse) => {
saveAs(res.data, `${params.exportFileName}.pdf`);
// 结束回调函数
if(endCallback) {
endCallback();
Notification.success({
title: '下载成功',
message: '请根据需要修改文件名称'
})
}
}).catch(() => {
// 结束回调函数
if(endCallback) {
endCallback();
Notification.error({
title: '下载失败',
message: '请检查网络或者联系管理员!'
})
}
})
//==============原生ajax方式==============
// var oReq = new XMLHttpRequest();
// // The Endpoint of your server
// var URLToPDF = params.PDFUrl;
// // Configure XMLHttpRequest
// oReq.open("GET", URLToPDF, true);
// // Important to use the blob response type
// oReq.responseType = "blob";
// // When the file request finishes
// // Is up to you, the configuration for error events etc.
// oReq.onload = function() {
// // Once the file is downloaded, open a new window with the PDF
// // Remember to allow the POP-UPS in your browser
// var file = new Blob([oReq.response], {
// type: 'application/pdf',
// });
// // Generate file download directly in the browser !
// saveAs(file, `${params.exportFileName}.pdf`);
// };
// oReq.send();
}
//源文件数组对象类型
export interface ISourceFileObj {
fileUrl: string,//文件地址
fileName: string//保存文件名
}
/**
* 打包压缩下载
* @param sourceFileObjArr 源文件数组对象数组
* @param zipName 压缩包的名称
*/
export const compressAndDownload = (
sourceFileObjArr: ISourceFileObj[],
zipName?: string,
startCallback?: Function,
endCallback?: Function
) => {
// 开始回调函数
if(startCallback) {
startCallback();
}
const getFile = (url: string) => {
return new Promise((resolve, reject) => {
const config: AxiosRequestConfig = {
url,
method: 'GET',
responseType: 'blob'
}
axios(config).then((res: AxiosResponse) => {
resolve(res.data);
}).catch((err: Error) => {
reject(err)
})
})
}
const zip = new JSZip();
const promises: any[] = []; //用于存储多个promise
sourceFileObjArr.forEach((item) => {
const promise = getFile(item.fileUrl).then((res: any) => {
const fileName = item.fileName
zip.folder(zipName ? zipName : "pdf压缩包")?.file(fileName, res ,{binary: true});
})
promises.push(promise)
})
Promise.all(promises).then(() => {
zip.generateAsync({
type: "blob",
compression: "DEFLATE", // STORE:默认不压缩 DEFLATE:需要压缩
compressionOptions: {
level: 9 // 压缩等级1~9 1压缩速度最快,9最优压缩方式
}
}).then((res: any) => {
saveAs(res, zipName ? zipName : "pdf压缩包") // 利用file-saver保存文件
// 结束回调函数
if(endCallback) {
endCallback();
Notification.success({
title: '下载成功',
message: '请根据需要修改文件名称'
})
}
}).catch(() => {
// 结束回调函数
if(endCallback) {
endCallback();
Notification.error({
title: '下载失败',
message: '请检查网络或者联系管理员!'
})
}
})
})
}
二、pdf预览
单个pdf预览可以通过直接跳转实现,但是,客户的需求是:
在自己系统的页面,预览 单个或多个 pdf
下面记录了实现技术点与思路:
/**技术点
// 1.pdf预览标签(currentPdfUrl变量是pdf地址)
<object :data="currentPdfUrl" type="application/pdf" width="100%" height="100%">
<embed :src="currentPdfUrl">
<p>
This browser does not support PDFs. Please download the PDF to view it:
<a :href="currentPdfUrl">Download PDF</a>
</p>
</object>
// 2.路由跳转打开新页面(vue-router路由跳转不会打开新页面,这里预览还是建议使用下面代码,跳转新页面预览)
const newThing = this.$router.resolve({path: '/single-report-preview'});
window.open(newThing.href, '_blank');
*/
/**思路
从 技术点1 已知能通过标签预览pdf,只需在自己的页面使用该标签,就已经实现pdf预览了
对于多个pdf预览,可在预览页面加上单选框,每次点击一个新选项,则切换为新的pdf地址
*/