关于多文件下载,往往需要压缩成一个zip压缩包返回前端进行下载,下面提供一些公共方法,希望能有帮助。
package com.example.upload;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.parallel.InputStreamSupplier;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.input.NullInputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
//定时将指定文件夹下的所有文件压缩
@Slf4j
public class ZipFilesUtil {
private static final String temPath = System.getProperty("java.io.tmpdir");
private static class FileInputStreamSupplier implements InputStreamSupplier {
private File file;
public FileInputStreamSupplier(File file) {
this.file = file;
}
@Override
public InputStream get() {
try {
if (file.isDirectory()) {
return new NullInputStream(0);
} else {
return new FileInputStream(file);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return new NullInputStream(0);
}
}
}
/**
* 下载文件,打包成zip压缩文件下载
*
* @param files
* @param response
* @return
* @throws Exception
*/
public static HttpServletResponse downLoadFiles(List<File> files, HttpServletResponse response) throws Exception {
try {
String zipFilePath = temPath + File.separator + System.currentTimeMillis();
File dir = new File(zipFilePath);
FileUtils.forceMkdir(dir);
// 压缩文件
File file = File.createTempFile(zipFilePath, ".zip");
if (!file.exists()) {
file.createNewFile();
}
response.reset();
// 创建文件输出流
FileOutputStream fous = new FileOutputStream(file);
ZipOutputStream zipOut = new ZipOutputStream(fous);
zipFile(files, zipOut);
zipOut.close();
fous.close();
return downloadZip(file, response);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return response;
}
public static HttpServletResponse downLoadFiles(List<File> files, String fileName, HttpServletResponse response) throws Exception {
try {
String zipFilePath = temPath + File.separator + fileName;
File dir = new File(zipFilePath);
FileUtils.forceMkdir(dir);
// 压缩文件
//File file = File.createTempFile(zipFilePath, ".zip");
File file = new File(zipFilePath, fileName + ".zip");
if (!file.exists()) {
file.createNewFile();
}
response.reset();
// 创建文件输出流
FileOutputStream fous = new FileOutputStream(file);
ZipOutputStream zipOut = new ZipOutputStream(fous);
zipFile(files, zipOut);
zipOut.close();
fous.close();
return downloadZip(file, response);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return response;
}
/**
* 把接受的全部文件打成压缩包
*
* @param files;
* @param outputStream
*/
public static void zipFile(List files, ZipOutputStream outputStream) {
int size = files.size();
for (int i = 0; i < size; i++) {
File file = (File) files.get(i);
zipFile(file, outputStream);
}
}
/**
* 根据输入的文件与输出流对文件进行打包
*
* @param inputFile
* @param ouputStream
*/
public static void zipFile(File inputFile, ZipOutputStream ouputStream) {
try {
if (inputFile.exists()) {
if (inputFile.isFile()) {
FileInputStream IN = new FileInputStream(inputFile);
BufferedInputStream bins = new BufferedInputStream(IN, 512);
ZipEntry entry = new ZipEntry(inputFile.getName());
ouputStream.putNextEntry(entry);
// 向压缩文件中输出数据
int nNumber;
byte[] buffer = new byte[512];
while ((nNumber = bins.read(buffer)) != -1) {
ouputStream.write(buffer, 0, nNumber);
}
// 关闭创建的流对象
bins.close();
IN.close();
} else {
try {
File[] files = inputFile.listFiles();
for (int i = 0; i < files.length; i++) {
zipFile(files[i], ouputStream);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 直接下载zip文件
*
* @param file
* @param response
* @return
*/
public static HttpServletResponse downloadZip(File file, HttpServletResponse response) {
if (file.exists() == false) {
log.info("待压缩的文件目录:" + file + "不存在.");
} else {
try {
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
// 如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
URLEncoder.encode(file.getName(), "UTF-8");
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(file.getName().getBytes("UTF-8"), "UTF-8"));
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
File f = new File(file.getPath());
f.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return response;
}
public static void compress(File f, String baseDir, ZipOutputStream zos){
if (!f.exists()) {
log.info("待压缩的文件目录或文件" + f.getName() + "不存在");
}
File[] fs = f.listFiles();
BufferedInputStream bis = null;
//ZipOutputStream zos = null;
byte[] bufs = new byte[1024 * 10];
FileInputStream fis = null;
try {
//zos = new ZipOutputStream(new FileOutputStream(zipFile));
for (int i = 0; i < fs.length; i++) {
String fName = fs[i].getName();
if (fs[i].isFile()) {
ZipEntry zipEntry = new ZipEntry(baseDir + fName);
zos.putNextEntry(zipEntry);
/**读取待压缩的文件并写进压缩包里*/
fis = new FileInputStream(fs[i]);
bis = new BufferedInputStream(fis, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
/**如果需要删除源文件,则需要执行下面2句*/
if(null != fis){
fis.close();
}
//fis.close();
fs[i].delete();
} else if (fs[i].isDirectory()) {
compress(fs[i], baseDir + fName + "/", zos);
//fis.close();
if(null != fis){
fis.close();
}
fs[i].delete();
}
}//end for
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//关闭流
try {
if (null != bis)
bis.close();
//if(null!=zos)
//zos.close();
if (null != fis)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下
*
* @param sourceFilePath :待压缩的文件路径
* @param zipFilePath :压缩后存放路径
* @param fileName :压缩后文件的名称
* @return
*/
public static HttpServletResponse fileToZip(HttpServletResponse response, String sourceFilePath, String zipFilePath, String fileName) {
boolean flag = false;
File sourceFile = new File(sourceFilePath);
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
if (sourceFile.exists() == false) {
log.info("待压缩的文件目录:" + sourceFilePath + "不存在.");
} else {
try {
File zipFile = new File(zipFilePath + "/" + fileName + ".zip");
if (zipFile.exists()) {
log.info(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
} else {
File[] sourceFiles = sourceFile.listFiles();
if (null == sourceFiles || sourceFiles.length < 1) {
log.info("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩.");
} else {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(new BufferedOutputStream(fos));
byte[] bufs = new byte[1024 * 10];
for (int i = 0; i < sourceFiles.length; i++) {
/**创建ZIP实体,并添加进压缩包*/
ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());
zos.putNextEntry(zipEntry);
/**读取待压缩的文件并写进压缩包里*/
fis = new FileInputStream(sourceFiles[i]);
bis = new BufferedInputStream(fis, 1024 * 10);
int read = 0;
while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
zos.write(bufs, 0, read);
}
}
flag = true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
//关闭流
try {
if (null != bis) bis.close();
if (null != zos) zos.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
try {
InputStream inputStream = new BufferedInputStream(new FileInputStream(zipFilePath));
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
// 清空response
response.reset();
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
// 如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-Disposition",
"attachment;filename=" + new String(fileName.getBytes("GB2312"), "ISO8859-1"));
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (Exception e) {
}
return response;
}
public static void main(String[] args) throws ParseException {
String sourceFilePath = "D:\\ProjectTest";
File sourceDir = new File(sourceFilePath);
File zipFile = new File(sourceFilePath + ".zip");
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(new FileOutputStream(zipFile));
String baseDir = "ProjectTest/";
compress(sourceDir, baseDir, zos);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (zos != null)
try {
zos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>upload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>upload</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- commons -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- common -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>