问题描述
- 笔者最近遇到一个需求
- 就是把后端接口返回的zip压缩包中的文件提取出来
- 并且解析拿到压缩包中的文件具体内容
- (比如,如果是txt文件,要读取其中的txt里面有哪些文字)
- 下载其中部分文件使用file-saver的saveAs方法
Nodejs的express提供一个接口返回一个zip压缩包
为了方便更好阅读,笔者用express提供了一个接口
route.get('/getZip', (req, res) => {
let zipUrl = './public/zip.zip'
res.header('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'application/zip');
res.setHeader('Content-Disposition', 'attachment; filename=zip.zip');
let readStream = fs.createReadStream(zipUrl)
readStream.pipe(res);
})
- 这样的话,我们就可以给这个接口发送请求,获取对应的压缩包文件了
- 接口地址:ashuai.work/api/getZip
- 当然,大家也可以复制粘贴到浏览器地址栏中回车直接下载
- zip压缩包内容如下:
下载jszip和file-saver
npm i jszip file-saver --save
"jszip": "^3.10.1",
"file-saver": "^2.0.5",
请求压缩包数据、并解压、再读取文件
比如,我是点击按钮请求数据
<template>
<div>
<button @click="downloadZipAndExtract">下载并提取压缩文件中的内容文件</button>
</div>
</template>
<script setup>
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import axios from 'axios';
const URL = 'http://ashuai.work/api/getZip'
const downloadZipAndExtract = () => {
axios.get(URL, { responseType: 'blob' })
.then(async response => {
const blob = response.data;
console.log('blob', blob)
})
.catch(error => {
console.error('下载失败', error);
});
};
</script>
上述打印结果如下图:
size是文件大小,289759字节大小;类型为zip
把接口返回的blob,交给zip去异步加载
const downloadZipAndExtract = () => {
axios.get(URL, { responseType: 'blob' })
.then(async response => {
const blob = response.data;
const zip = new JSZip();
await zip.loadAsync(blob);
console.log('zip', zip)
})
.catch(error => {
console.error('下载失败', error);
});
};
上述打印结果如下:我们已经可以看到zip压缩包中的文件有哪些了
遍历zip中的files,既可拿到对应文件,再使用FileReader读取内容
const blob = response.data;
const zip = new JSZip();
await zip.loadAsync(blob);
zip.forEach((relativePath, file) => {
if (!file.dir) {
file.async('blob').then(content => {
const reader = new FileReader();
reader.onload = (e) => {
console.log('文件内容------>', e.target.result);
}
reader.readAsText(content);
saveAs(content, file.name);
})
}
});
上述打印文件内容如下:
完整代码
复制粘贴即用
<template>
<div>
<button @click="downloadZipAndExtract">下载并提取压缩文件中的内容文件</button>
</div>
</template>
<script setup>
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import axios from 'axios';
const URL = 'http://ashuai.work/api/getZip'
const downloadZipAndExtract = () => {
axios.get(URL, { responseType: 'blob' })
.then(async response => {
const blob = response.data;
const zip = new JSZip();
await zip.loadAsync(blob);
zip.forEach((relativePath, file) => {
if (!file.dir) {
file.async('blob').then(content => {
const reader = new FileReader();
reader.onload = (e) => {
console.log('文件内容------>', e.target.result);
}
reader.readAsText(content);
saveAs(content, file.name);
})
}
});
})
.catch(error => {
console.error('下载失败', error);
});
};
</script>
地址:
- jszip:www.npmjs.com/package/jsz…
- file-saver:www.npmjs.com/package/fil…
jszip在线压缩
- jszip除了能够解压zip压缩包中文件之外
- 还能够把文件(文件夹)压缩成zip包
- 如下的html文件
- 复制粘贴即用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zip压缩文件和文件夹</title>
<script src="https://www.mdo.ink/upload/jszip.min.js"></script>
</head>
<body>
<h1>文件和文件夹压缩</h1>
<button id="compressFiles">压缩文件</button>
<button id="compressFolder">压缩文件夹</button>
<input type="file" id="fileInput" multiple style="display: none;">
<input type="file" id="folderInput" webkitdirectory directory style="display: none;">
<script>
const compressFilesButton = document.getElementById('compressFiles');
const compressFolderButton = document.getElementById('compressFolder');
const fileInput = document.getElementById('fileInput');
const folderInput = document.getElementById('folderInput');
compressFilesButton.addEventListener('click', () => {
fileInput.click();
});
compressFolderButton.addEventListener('click', () => {
folderInput.click();
});
fileInput.addEventListener('change', async () => {
const files = fileInput.files;
if (files.length > 0) {
await compressAndDownload(files, 'compressed_files.zip');
}
});
folderInput.addEventListener('change', async () => {
const files = folderInput.files;
if (files.length > 0) {
await compressAndDownload(files, 'compressed_folder.zip');
}
});
async function compressAndDownload(files, zipFileName) {
const zip = new JSZip();
for (let i = 0; i < files.length; i++) {
const file = files[i];
const relativePath = file.webkitRelativePath || file.name;
zip.file(relativePath, file);
}
const content = await zip.generateAsync({ type: 'blob' });
const link = document.createElement('a');
link.href = URL.createObjectURL(content);
link.download = zipFileName;
link.click();
URL.revokeObjectURL(link.href);
}
</script>
</body>
</html>