下载https文件并打包成ZIP
2021-01-14 07:14
标签:class pack 标识 io操作 entry flush jsse ring gets 首先Controller层代码 下载https文件并打包成ZIP 标签:class pack 标识 io操作 entry flush jsse ring gets 原文地址:https://www.cnblogs.com/sunzy-blog/p/13447835.html 1 @RequestMapping(value = "downloadZipFile")
2 @OptionsLog(optDesc = "打包影印件下载", optType = "返现日志")
3 public void downloadZipFile(HttpServletResponse response, String id) throws IOException {
4 String zipName = "myfile.zip";
5 response.setContentType("APPLICATION/OCTET-STREAM");
6 response.setHeader("Content-Disposition", "attachment; filename=" + zipName);
7 ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
8 try {
9 List
ZipEntry是zip下面的文件条目,你可以比作外面系统的File类似。
后面的参数就是在zip目录下的相对位置。
所以这里有一点比较重要的就是当你遍历文件夹的时候你的ZipEntry的参数的改变规律。
写不好的话会使整个文件目录混乱(如果文件层级较低那就不碍事)。
而putNextEntry(ZipEntry z)的意思就是我下面io操作(写入)都是在z这个文件条目下进行的。zipoutputstream流和其他的output流不一样的地方就是BufferedOutputStream不能嵌套它。
也就是它不能套缓存流用。对于文件夹下包含文件夹需要特殊考虑。判断它是不是文件夹。
文件夹的话要遍历他的子节点文件。用递归思想。已在代码中给出注释。还有文件要注意相对绝对路径。package com.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.DataInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author 孙正扬
* @date 2020-08-04 17:21:22
*/
public class ZipUtils {
private static Logger logger = LoggerFactory.getLogger(ZipUtils.class);
/**
* 获取https路径的文件打包成zip文件
*
* @param httpUrl
* @param out
*/
public static void doZip(String fileName, String httpUrl, ZipOutputStream out) {
InputStream in = null;
File file = null;
try {
if (httpUrl.startsWith("https://")) {
/**
* 设置忽略ssl证书
*/
SSLContext sslcontext = null;
sslcontext = SSLContext.getInstance("SSL", "SunJSSE");
sslcontext.init(null, new TrustManager[]{new X509TrustUtiil()}, new java.security.SecureRandom());
HostnameVerifier ignoreHostnameVerifier = new myHostnameVerifier();
URL url = new URL(httpUrl);
HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
HttpsURLConnection urlCon = (HttpsURLConnection) url.openConnection();
urlCon.setConnectTimeout(6000);
urlCon.setReadTimeout(6000);
int code = urlCon.getResponseCode();
if (code != HttpURLConnection.HTTP_OK) {
try {
throw new Exception("文件读取失败");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* ZipEntry是zip下面的文件条目,你可以比作外面系统的File类似。
* 后面的参数就是在zip目录下的相对位置。所以这里有一点比较重要的就是当你遍历文件夹的时候你的ZipEntry的参数的改变规律。
* 写不好的话会使整个文件目录混乱(如果文件层级较低那就不碍事)。
* 而putNextEntry(ZipEntry z)的意思就是我下面io操作(写入)都是在z这个文件条目下进行的。
*/
String[] zips = httpUrl.split("/");
String[] lastName = httpUrl.split("\\.");
ZipEntry entry = new ZipEntry(fileName == null ? zips[zips.length - 1] : fileName + "." + lastName[lastName.length - 1]);
/**
* zipoutputstream流和其他的output流不一样的地方就是BufferedOutputStream不能嵌套它。也就是它不能套缓存流用。
* 对于文件夹下包含文件夹需要特殊考虑。判断它是不是文件夹。
* 文件夹的话要遍历他的子节点文件。用递归思想。已在代码中给出注释。还有文件要注意相对绝对路径。
*/
out.putNextEntry(entry);
byte[] buffer = new byte[2048];
// 读文件流
in = new DataInputStream(urlCon.getInputStream());
int len = 0;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
out.flush();
}
out.closeEntry();
in.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
/**out流在最外层关闭,如果循环的话提前关闭会直接报错*/
if (null != in) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
/**
* [强制]在实现的HostnameVerifier子类中,
* 需要使用verify函数效验服务器主机名的合法性,否则会导致恶意程序利用中间人攻击绕过主机名效验。
* 说明:
* 在握手期间,如果URL的主机名和服务器的标识主机名不匹配,
* 则验证机制可以回调此接口实现程序来确定是否应该允许此连接,
* 如果回调内实现不恰当,默认接受所有域名,则有安全风险
*/
class myHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}
下一篇:php中浮点数计算问题