前言:汇总一下做过的下载功能,持续补充中
一、将后端传过来的二进制流文件下载(需要提取headers里面的文件名)
const { herders,data }=res;
// 创建下载链接元素
const link = document.createElement("a");
// 创建 Blob 对象,将服务器响应的数据作为 Blob 的内容
const blob = new Blob([data], { type: "application/vnd.ms-excel" });
// 解析服务器响应头中的 Content-Disposition 字段获取文件名
var patt = new RegExp("filename=([^;]+\\.[^\\.;]+);*");
var contentDisposition = decodeURI(headers["content-disposition"]);
var result = patt.exec(contentDisposition);
var fileName = result[1];
fileName = fileName.replace(/\"/g, "");
// 隐藏下载链接元素
link.style.display = "none";
// 设置下载链接的属性
link.href = URL.createObjectURL(blob);
link.setAttribute("download", fileName);
// 将下载链接添加到页面中
document.body.appendChild(link);
// 模拟点击下载链接
link.click();
// 移除下载链接元素
document.body.removeChild(link);
以上代码可以直接copy进你的点击事件,然后根据你和后端约定的稍微改一下就行
需要理解的点:
1、res是后端传给我的数据,data是二进制流文件,headers里面有我需要的文件名,所以我将他们提取出来了;
2、创建blob时的type是用来指定不同的媒体类型(MIME),就是你要下载什么文件,我上面例子写的application/vnd.ms-excel就是微软 Excel 文件,那么就会下载成一个excel文件;
其他常见的MIME类型:
text/plain
:纯文本文件,通常用于.txt
文件。text/html
:HTML 文件,用于网页文档。application/json
:JSON 数据,用于传输和存储结构化数据。application/pdf
:PDF 文件,用于可移植文档格式。image/jpeg
:JPEG 图像文件。image/png
:PNG 图像文件。audio/mp3
:MP3 音频文件。video/mp4
:MP4 视频文件。
这只是一小部分常见的MIME类型,实际上有很多种不同的MIME类型,每种类型对应不同的文件格式或媒体类型,要根据需要来选择。
3、这些是用正则去卡文件名的操作,需要根据你的需求灵活变动
二、将后端传过来的二进制流文件下载(不需要提取文件名,前端来决定下载下来的文件叫什么
)
//创建 Blob 对象
const blob = new Blob([row.traffic_meta], { type: "text/plain" });
// 创建下载链接
const url = URL.createObjectURL(blob);
// 创建下载按钮
const downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = "example.txt"; // 设置下载文件的文件名
// 将按钮添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击下载链接
downloadLink.click();
// 移除下载按钮
document.body.removeChild(downloadLink);
以上代码没有取后端传的文件名,是前端自己定义的,row.traffic_meta是二进制流文件,用的时候记得替换
三、将表格数据(数组)下载成csv文件
1、需求描述:下载一个表格,但是后端不传二进制文件流,而是接口返回给前端的数组。
类似这样的数据:
const tableData=[
{name: '1',value: 1},
{name: '2',value: 2},
{name: '3',value: 3},
{name: '4',value: 4},
{name: '5',value: 5},
{name: '6',value: 6},
{name: '7',value: 7},
]
要下载成一个csv,表头就是name和value
2、在utils创建一个js文件Export2Csv.js:
function processRow(row) {
let finalVal = ''
for (let j = 0; j < row.length; j++) {
let innerValue = row[j] === null ? '' : row[j].toString()
if (row[j] instanceof Date) {
innerValue = row[j].toLocaleString()
}
let result = innerValue.replace(/"/g, '""')
if (result.search(/("|,|\n)/g) >= 0) { result = '"' + result + '"' }
if (j > 0) { finalVal += ',' }
finalVal += result
}
return finalVal + '\n'
}
export function exportToCsv(filename, rows) {
let csvFile = ''
for (let i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i])
}
// 添加\ufeff头,标识excel可以打开UTF8编码的文件
const blob = new Blob(['\ufeff', csvFile], { type: 'text/csv;charset=utf-8;' })
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename)
} else {
const link = document.createElement('a')
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
const url = URL.createObjectURL(blob)
link.setAttribute('href', url)
link.setAttribute('download', filename)
link.style.visibility = 'hidden'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
}
}
export function exportToCsv_zl(filename, rows) {
let csvFile = ''
for (let i = 0; i < rows.length; i++) {
csvFile += processRow(rows[i])
}
// 添加\ufeff头,标识excel可以打开UTF8编码的文件
// const blob= new Blob(['\ufeff', csvFile], { type: 'text/csv;charset=utf-8;' })
console.log(csvFile);
return csvFile
}
export function exportDictArray2csv(data, filename,zl) {
const keys = Object.keys(data[0])
const rows = []
// writer header
rows.push(keys)
data.forEach(dict => {
const row = []
keys.forEach(key => {
row.push(dict[key])
})
rows.push(row)
})
if(zl){
return exportToCsv_zl(filename,rows)
}else{
exportToCsv(filename, rows)
}
}
export default exportDictArray2csv
3、 导入在需要该功能的页面里使用
import { exportDictArray2csv } from "@/utils/Export2Csv.js";
const filename = `data.csv`;
exportDictArray2csv(tableData.value, filename);
四、将16进制转化为pcap包并下载
1、方法代码:
// 将十六进制字符串转换为字节数组
function hexToBytes(hex) {
const bytes = [];
for (let i = 0; i < hex.length; i += 2) {
bytes.push(parseInt(hex.substr(i, 2), 16));
}
return new Uint8Array(bytes);
}
// 构建 PCAP 文件头
function createPcapHeader() {
const header = new Uint8Array(24);
const dataView = new DataView(header.buffer);
dataView.setUint32(0, 0xa1b2c3d4, true); // magic number
dataView.setUint16(4, 2, true); // version major
dataView.setUint16(6, 4, true); // version minor
dataView.setUint32(8, 0, true); // timezone
dataView.setUint32(12, 0, true); // sigfigs
dataView.setUint32(16, 65535, true); // snaplen
dataView.setUint32(20, 1, true); // linktype
return header;
}
// 创建 PCAP 数据包(这里仅作为示例,你需要根据具体数据填充)
function createPcapPacket(data) {
const packetHeader = new Uint8Array(16);
const dataView = new DataView(packetHeader.buffer);
const timestamp = Math.floor(Date.now() / 1000); // 当前时间戳
const microseconds = (Date.now() % 1000) * 1000; // 微秒部分
const length = data.length;
dataView.setUint32(0, timestamp, true); // seconds
dataView.setUint32(4, microseconds, true); // microseconds
dataView.setUint32(8, length, true); // number of octets of packet saved in file
dataView.setUint32(12, length, true); // actual length of the packet
return { header: packetHeader, data };
}
// 主函数
function createPcapFile(hexString) {
const pcapHeader = createPcapHeader();
const packetData = hexToBytes(hexString);
const pcapPacket = createPcapPacket(packetData);
// 拼接 PCAP 文件内容
const pcapFile = new Uint8Array(
pcapHeader.length + pcapPacket.header.length + pcapPacket.data.length
);
pcapFile.set(pcapHeader, 0);
pcapFile.set(pcapPacket.header, pcapHeader.length);
pcapFile.set(pcapPacket.data, pcapHeader.length + pcapPacket.header.length);
return pcapFile;
}
2、使用该方法:
const pcapFile = createPcapFile(pkt_data);
const blob1 = new Blob([pcapFile], { type: "application/octet-stream" });
// 创建下载链接
const url = URL.createObjectURL(blob1);
// 创建下载按钮
const downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = "命中流量.pcap"; // 设置下载文件的文件名
// 将按钮添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击下载链接
downloadLink.click();
// 移除下载按钮
document.body.removeChild(downloadLink);
五、将两个文件合成zip下载
1、先下载插件
npm i jszip
2、导入并使用
import JSZip from "jszip";
import { saveAs } from "file-saver";
const blob1 = res.data;
const blob2 = new Blob(
["\ufeff", exportDictArray2csv([row], "filename.csv", true)],
{ type: "text/csv;charset=utf-8;" }
);
const zip = new JSZip();
// 将 blob 数据添加到 ZIP 文件
zip.file(`原始流量.pcap`, blob1);
zip.file("告警事件.csv", blob2);
// 生成 ZIP 文件
const zipBlob = await zip.generateAsync({ type: "blob" });
saveAs(zipBlob, "files.zip");
以上代码就是将两个bolb传入插件并下载成了一个zip,解压之后就是: