生成压缩包工具生成代码
package com.util;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.FileCopyUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Locale;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 生成压缩包
*/
@Slf4j
public class ZipCompressor {
@SneakyThrows
public static void getZip(String zipName, File zipFile, HttpServletRequest request, HttpServletResponse response, File... files) {
try (
// 作用是为任何OutputStream产生校验和
FileOutputStream fos = new FileOutputStream(zipFile);
// 第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)
CheckedOutputStream cos = new CheckedOutputStream(fos, new Adler32());
// 用于将数据压缩成zip文件格式
ZipOutputStream zos = new ZipOutputStream(cos)
) {
// 循环根据路径从OSS获得对象,存入临时文件zip中
for (File file : files) {
compressFile(zos, file, file.getName());
}
zos.close();
String header = request.getHeader(CommonConstants.USER_AGENT).toUpperCase(Locale.ROOT);
// IE下载文件名空格变+号问题
zipName = URLEncoder.encode(zipName, CommonConstants.UTF_8);
zipName = zipName.replace("+", "%20");
// 设置响应类型,以附件形式下载文件
response.reset();
response.setContentType("text/plain");
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Location", zipName);
response.setHeader("Cache-Control", "max-age=0");
response.setHeader("Content-Disposition", "attachment; filename=" + zipName);
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 下载流封装
try (FileInputStream fis = new FileInputStream(zipFile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
// 下载zip文件
FileCopyUtils.copy(bis, bos);
// 删除临时zip文件
boolean delete = zipFile.delete();
}
} catch (Exception exception) {
log.error("getZip error: ", exception);
}
}
private static void compressFile(ZipOutputStream zos, File sourceFile, String baseName) throws IOException {
if (!sourceFile.exists()) {
return;
}
// 若路径为目录(文件夹)
BasicFileAttributes basicFileAttributes = Files.readAttributes(sourceFile.toPath(), BasicFileAttributes.class);
if (basicFileAttributes.isDirectory()) {
// 取出文件夹中的文件(或子文件夹)
File[] fileList = sourceFile.listFiles();
// 若文件夹为空,则创建一个目录进入点
assert fileList != null;
if (fileList.length == 0) {
// 文件名称后跟File.separator表示这是一个文件夹
zos.putNextEntry(new ZipEntry(baseName + File.separator));
// 若文件夹非空,则递归调用compressFile,对文件夹中的每个文件或每个文件夹进行压缩
} else {
for (File file : fileList) {
compressFile(zos, file, baseName + File.separator + file.getName());
}
}
// 若为文件,则先创建目录进入点,再将文件写入zip文件中
} else {
ZipEntry zipEntry = new ZipEntry(baseName);
// 设置ZipEntry的最后修改时间为源文件的最后修改时间
zipEntry.setTime(basicFileAttributes.lastModifiedTime().toMillis());
zos.putNextEntry(zipEntry);
try (FileInputStream fis = new FileInputStream(sourceFile)) {
copyStream(fis, zos);
} catch (Exception exception) {
log.error("输入流关闭异常:", exception);
}
}
}
/**
* 流拷贝
*
* @param inputStream 输入流
* @param outputStream 输出流
*/
private static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
int bufferLength = 1024 * 100;
int count;
byte[] buffer = new byte[bufferLength];
while ((count = inputStream.read(buffer, 0, bufferLength)) != -1) {
outputStream.write(buffer, 0, count);
}
outputStream.flush();
}
}
应用代码
java
@RequestMapping(value = "/getZip", method = RequestMethod.POST)
public void getZip(@RequestParam("name") String name, HttpServletRequest request, HttpServletResponse response) {
if (StringUtils.isBlank(name)) {
log.info("getZip error: name is not empty");
return;
}
File file = new File("文件夹路径");
File subFile = new File(file, "子文件夹名称");
String zipName = eventName + ".zip";
try {
// 创建临时文件
File zipFile = FileUtil.createTempFile(eventName, ".zip", true);
// 下载文件为zip压缩包
ZipCompressor.getZip(zipName, zipFile, request, response, subFile);
log.info("getZip end.");
} catch (Exception exception) {
log.error("getZip error: ", exception);
} finally {
// 删除生成的文件和文件夹
if (file.exists()) {
try {
FileUtils.forceDelete(file);
} catch (Exception exception) {
log.error("forceDelete error ", exception);
}
}
}
}
react
jsonSchema2pojo = () => {
const formData = new FormData();
formData.append('name', "名称");
const xhr = new XMLHttpRequest();
xhr.open('POST', apiPrefix + '/getZip', true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (xhr.status === 200) {
let filename
var type = xhr.getResponseHeader('content-type')
// 后台返回了名字则用后台的名字
var contentDisposition = xhr.getResponseHeader('content-disposition')
if (!filename && contentDisposition) {
var idx = contentDisposition.indexOf('filename=')
if (idx > -1) {
filename = decodeURIComponent(contentDisposition.substring(idx + 9))
}
}
var blob = xhr.response
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename)
} else {
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob, {
type: type
})
// 创建下载的链接
downloadElement.href = href
// 下载后文件名
downloadElement.download = filename
document.body.appendChild(downloadElement)
// 点击下载
downloadElement.click()
// 下载完成移除元素
document.body.removeChild(downloadElement)
// 释放掉blob对象
window.URL.revokeObjectURL(href)
}
}
}
xhr.send(formData);
}