前言
- 根据URL网络地址压缩包解压获取到所有文件并筛选文件递归目录及文件再进行压缩输出流到浏览器下载
maven添加
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
一、根据URL获取到InputStream
- 根据URL获得数据的输入流
/**
* 根据地址获得数据的输入流
*
* @param strUrl 网络连接地址
* @return url的输入流
*/
public static InputStream getInputStreamByUrl(String strUrl) {
HttpURLConnection conn = null;
try {
URL url = new URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(20 * 1000);
final ByteArrayOutputStream output = new ByteArrayOutputStream();
IOUtils.copy(conn.getInputStream(), output);
return new ByteArrayInputStream(output.toByteArray());
} catch (Exception e) {
logger.error(e + "");
} finally {
try {
if (conn != null) {
conn.disconnect();
}
} catch (Exception e) {
logger.error(e + "");
}
}
return null;
}
二、解压,所以需要先用GzipCompressorInputStream流包装文件流
- 使用HttpServletResponse 传输输出流到浏览器下载
代码如下(示例):
public static void getZIP(HttpServletResponse response, String downUrl) throws IOException {
response.reset(); // 重点突出
// 不同类型的文件对应不同的MIME类型
InputStream is = getInputStreamByUrl(downUrl);
//先解压,所以需要先用gzip流包装文件流
CompressorInputStream gis = new GzipCompressorInputStream(is);
// 在解包,用tar流包装gzip流 注意因为这里所有URL文件包都是tar.gz压缩包,这里要跟据业务需求来
try (ArchiveInputStream ais = new TarArchiveInputStream(gis)) {
ArchiveEntry nextEntry;
response.setContentType("application/octet-stream; charset=UTF-8");
//这里是根据日期时间来命名zip包
String fileName = getDateTime() + ".zip";
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
// 获取输出流
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
ZipOutputStream zipOutputStream = new ZipOutputStream(bos);
while ((nextEntry = ais.getNextEntry()) != null) {
String name = nextEntry.getName();
//筛选文件和文件夹
//业务需求筛选文件夹,注意父级文件夹最好是不要过滤
//if (true) {
Path path = Paths.get(name);
//递归目录及文件输出方法,注意这里的name不是文件名,name是目录或目录及文件
zipFile(ais, path.toFile(), name, zipOutputStream);
//}
}
zipOutputStream.close();
ais.close();
gis.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
三、递归目录及文件输出流
代码如下(示例): 可参考知乎作者:字母哥
- 虽然我也是参考该作者的,有的坑已经帮各位踩了并加了注释
/**
* 将fileToZip文件夹及其子目录文件递归压缩到zip文件中
* @param fileToZip 递归当前处理对象,可能是文件夹,也可能是文件
* @param fileName 文件夹名称或文件夹+文件名称
* @param zipOut 压缩文件输出流
* @throws IOException
*/
private static void zipFile(ArchiveInputStream ais,File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
//不压缩隐藏文件夹 因是URL网络地址压缩包可不用判断四分是隐藏文件或文件夹
/*if (fileToZip.isHidden()) {
return;
}*/
//判断压缩对象如果是一个文件夹, 这里判断isDirectory()方法是有bug的,建议自己写逻辑判断
if (fileToZip.isDirectory()) {
if (fileName.endsWith("/")) {
//如果文件夹是以“/”结尾,将文件夹作为压缩箱放入zipOut压缩输出流
zipOut.putNextEntry(new ZipEntry(fileName));
zipOut.closeEntry();
} else {
//如果文件夹不是以“/”结尾,将文件夹结尾加上“/”之后作为压缩箱放入zipOut压缩输出流
zipOut.putNextEntry(new ZipEntry(fileName + "/"));
zipOut.closeEntry();
}
//遍历文件夹子目录,进行递归的zipFile
File[] children = fileToZip.listFiles();
for (File childFile : children) {
zipFile(ais,childFile, fileName + "/" + childFile.getName(), zipOut);
}
//如果当前递归对象是文件夹,加入ZipEntry之后就返回
return;
}
//这里不要使用FileInputStream存储文件,因为会抛出异常“系统找不到指定文件”
//存放目录
ZipEntry zipEntry = new ZipEntry(fileName);
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[BUFFER_SIZE];
int length;
while ((length = ais.read(bytes)) >= 0) {
//输出文件流
zipOut.write(bytes, 0, length);
}
//注意不要在这关闭输出流,所有循环结束再关闭输出流,不然浏览器下载解压文件大小为0kb,或文件已损坏
}
以上就是作者对URL网络地址文件压缩包筛选并递归目录及文件输出的思路了,如对你有帮助对作者点点赞
如有侵权请及时联系作者,作者是新人请多多包含谢谢