主推方法
先来推一手比较简短的方法,利用XMLHttpRequest实现下载功能 封装方法
export function downloadFile(obj: { name: string, url: string }) {
var xhr = new XMLHttpRequest()
xhr.open('get', process.env.VUE_APP_FILE_DOWNLOAD + obj.url)
xhr.responseType = 'blob'
// 关键部分
xhr.onload = function (e) {
// 如果请求执行成功
if (this.status === 200) {
var blob = this.response
var a = document.createElement('a')
a.href = window.URL.createObjectURL(blob)
a.download = obj.name
a.click()
// 释放之前创建的URL对象
window.URL.revokeObjectURL(blob)
}
}
xhr.send()
}
调用方法
downloadFile({ name: string, url: string });
0.常见new Blob属性type参考地址
1.实现一个xlsx下载功能
1.1封装一个下载xlsx的文件的axios实例
import axios from 'axios'
// import store from '@/store'
import router from '@/router'
import { getToken } from '@/utils/auth'
console.log('axios.defaults',axios.defaults)
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000,
responseType: 'blob'
})
// var tableName = '' // 定义表格名称
// request interceptor
service.interceptors.request.use(
config => {
const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
console.log('service.defaults',service.defaults)
// response interceptor
service.interceptors.response.use(
response => {
const blob = new Blob([response.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
let contentDisposition = null
let result = null
let fileName = router.currentRoute.meta.title
if (response.headers['content-disposition'] != undefined) {
// 文件名称存在得的情况下
contentDisposition = decodeURI(response.headers['content-disposition'])
result = patt.exec(contentDisposition)
fileName = result[1]
fileName = fileName.replace(/\"/g, '')
}
const objectUrl = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = objectUrl
a.download = fileName
if ('download' in document.createElement('a')) {
// 支持a标签download的浏览器
// 下面这个写法兼容火狐
a.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
})
)
window.URL.revokeObjectURL(blob)
} else {
// 其它浏览器
navigator.msSaveBlob(blob, fileName)
}
}
)
export default service
1.2封装一个下载的方法,调用上面封装的下载xlsx功能
export function exportDeclareList(params){
return downloadRequest({
url: `/attestationWork/exportDeclareList`,
method:'GET',
params,
})
}
1.3调用这个方法,实现效果
2.实现一个下载pips文件的功能
下载功能除了响应拦截跟1.1不一样其它地方都一样
1.1封装下载请求axios实例
// 响应请求拦截
service.interceptors.response.use(
response => {
const blob = new Blob([response.data], {
type: 'application/octet-stream'
})
const patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
let contentDisposition;
let result;
let fileName="某个pips文件.pips";
if (response.headers['content-disposition'] != undefined) {
// 文件名称存在得的情况下
contentDisposition = decodeURI(response.headers['content-disposition'])
result = patt.exec(contentDisposition)
fileName = result[1]
fileName = fileName.replace(/"/g, '')
console.log('fileName',fileName)
}
const objectUrl = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = objectUrl
a.download = fileName
if ('download' in document.createElement('a')) {
// 支持a标签download的浏览器
// 下面这个写法兼容火狐
a.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
})
)
// 释放这个临时的对象url
window.URL.revokeObjectURL(objectUrl)
} else {
// 其它浏览器
// navigator.msSaveBlob(blob, fileName)
}
}
)
2.1实现效果
3.前端根据节点生成一个pdf并下载
需要用到两个插件html2canvas,jspdf
3.1封装一个文件exportDataPdf.ts
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf'
function exportDataPdf(el: HTMLElement, fileName: string) {
html2canvas(el, {
scale: 3, // 设置缩放
useCORS: true, // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
allowTaint: true,
logging: false, // 打印日志用的 可以不加默认为false
backgroundColor: '#ffffff'
}).then((canvas) => {
const contentWidth = canvas.width;
const contentHeight = canvas.height;
// 一页pdf显示html页面生成的canvas高度;
const pageHeight = (contentWidth / 592.28) * 841.89;
// 未生成pdf的html页面高度
let leftHeight = contentHeight;
// 页面偏移
let position = 0;
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
const imgWidth = 595.28;
const imgHeight = (595.28 / contentWidth) * contentHeight;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
// 添加水印
// ctx.textAlign = 'center';
// ctx.textBaseline = 'middle';
// ctx.rotate((25 * Math.PI) / 180);
ctx.font = '20px Microsoft Yahei';
// ctx.fillStyle = 'rgba(184, 184, 184, 0.8)';
// for (let i = contentWidth * -1; i < contentWidth; i += 240) {
// for (let j = contentHeight * -1; j < contentHeight; j += 100) {
// // 填充文字,x 间距, y 间距
// ctx.fillText('水印名', i, j);
// }
// }
const pageData = canvas.toDataURL('image/jpeg', 1.0);
const pdf = new jsPDF("p", "pt", "a4");
if (leftHeight < pageHeight) {
// 在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
} else {
// 分页
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
// 可动态生成
pdf.save(`${fileName}.pdf`);
})
}
export default exportDataPdf;
3.2调用exportDataPdf方法
<div ref="pdfDomContainer"></div>
let pdfDomContainer = ref<HTMLElement>();
exportDataPdf(pdfDomContainer.value, '某某pdfwen文件名字不带后缀');
3.3实现效果如下
4.前端根据word模板充填数据并下载充填好数据的word
4.1封装一个方法文件
import Docxtemplater from "docxtemplater"
import PizZip from "pizzip"
import JSZipUtils from "jszip-utils"
import { saveAs } from 'file-saver'
import expressions from "angular-expressions"
import { assign } from "lodash"
export default function ExportBriefDataDocx(tempDocxPath, data, fileName) {
expressions.filters.lower = function(input) {
if (!input) return input
// toLowerCase() 方法用于把字符串转换为小写。
return input.toLowerCase()
}
function angularParser(tag) {
tag = tag
.replace(/^\.$/, 'this')
.replace(/(’|‘)/g, "'")
.replace(/(“|”)/g, '"')
const expr = expressions.compile(tag)
return {
get: function(scope, context) {
let obj = {}
const scopeList = context.scopeList
const num = context.num
for (let i = 0, len = num + 1; i < len; i++) {
obj = assign(obj, scopeList[i])
}
return expr(scope, obj)
}
}
}
JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
if (error) {
console.log(error)
}
// 创建一个JSZip实例,内容为模板的内容
const zip = new PizZip(content)
// 创建并加载 Docxtemplater 实例对象
const doc = new Docxtemplater(zip, { parser: angularParser })
// 设置模板变量的值
doc.setData(data)
try {
// 呈现文档,会将内部所有变量替换成值,
doc.render()
} catch (error) {
const e = {
message: (error as any).message,
name: (error as any).name,
stack: (error as any).stack,
properties: (error as any).properties
}
console.log({ error: e })
// 当使用json记录时,此处抛出错误信息
throw error
}
// 生成一个代表Docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, fileName)
})
}
4.2调用ExportBriefDataDocx方法
function exportDocx() {
state.docxData.tableData = state.tableData
const fileUrl = new URL(`../../../../assets/report.docx`, import.meta.url).href
ExportBriefDataDocx(fileUrl, state.docxData, state.docxData.title+'.docx')
}