一、使用工具
* java.utils 下的ZipOutputStream
* java.net 的http请求工具 HttpURLConnection
二、 zip下载
1. 通过浏览器以附件的形式下载到客户端
思路:
response 的write方法要写出一个byte[],所以我们需要从ZipStreamOutputStream中获取到byte[]。 在java中从io流中获取byte的办法就是将
io流写到字节数组输出流中ByteArrayOutputStream(即内存中)。 代码如下:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipStreamOutputStream zos = new ZipStreamOutputStream(bos)
// 向zos中写数据 ...
byte[] data = bos.toByteArray();
分析数据流流向如下:
图片字节数据byte[](jpg) --> ZipStreamOutputStream --> ByteArrayOutputStream -> byte[](zip)
2. 下载到服务器文件目录下
分析数据流流向如下:
图片字节数据byte[](jpg) --> ZipStreamOutputStream --> FileOutputStream -> File(zip)
三、 注意点
1. 在向ZipOutputStream中写完数据后,必须马上关闭ZipOutputStream,否则zip文件会损坏
2. 对于包装流,关闭流的顺序问题
一层套一层的包装流,关闭顺序一定是先关闭外层包装流,然后再关闭内层的流,否则会文件损坏,而且在关闭外层流的时候会报流已经关闭异常
四、 实践代码
` /**
* 图像下载接口, 返回base64编码的图像信息
*
* @param response
* @param imgType
* @throws IOException
*/
@GetMapping("/getImage")
public void imageDownloadServer(HttpServletResponse response, String imgType) throws IOException {
response.setContentType("text/plain");
ServletOutputStream outputStream = response.getOutputStream();
BASE64Encoder encoder = new BASE64Encoder();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
File file = null;
if ("F".equals(imgType)) {
file = new File("C:\\Users\\cheva\\Desktop\\票样\\1.jpg");
} else {
file = new File("C:\\Users\\cheva\\Desktop\\票样\\2.jpg");
}
InputStream fis = new FileInputStream(file);
int len = -1;
byte[] buff = new byte[1024];
while ((len = fis.read(buff)) != -1) {
bos.write(buff, 0, len);
}
bos.flush();
String base64 = encoder.encode(bos.toByteArray());
fis.close();
bos.close();
outputStream.write(base64.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
/**
* 以附件的形式下载到客户端
* @param request
* @param response
*/
@GetMapping("/download")
public void dowload(HttpServletRequest request, HttpServletResponse response) {
ByteArrayOutputStream bos = null;
ZipOutputStream zipOutputStream = null;
String outName = "my.zip";
// 1. 向ZipOutputStream中写入数据。 流的走向: 数据字节 -> ZipOutputStream -> ByteArrayOutputStream
// 注意: 在向ZipOutputStream中写完数据后,必须马上关闭ZipOutputStream,否则zip文件会损坏
/**
* 如下代码下载的zip文件会损坏
* try {
* response.setContentType("application/zip");
* response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(outName, "UTF-8"));
* bos = new ByteArrayOutputStream();
* zipOutputStream = new ZipOutputStream(bos);
* packageZipStream("0011", zipOutputStream);
* outputStream = response.getOutputStream();
* outputStream.write(bos.toByteArray());
* } catch (Exception e) {
* e.printStackTrace();
* } finally {
* if (zipOutputStream != null) {
* try {
* zipOutputStream.close();
* } catch (Exception e) {
* System.out.println("流关闭异常");
* }
* }
* if (bos != null) {
* try {
* bos.close();
* } catch (Exception e) {
* System.out.println("流关闭异常");
* }
* }
* }
* 原因在于在使用respose输出字节数组的时候,zipoutputstream还没有关闭,导致文件损坏,代码应该如下
*/
try {
bos = new ByteArrayOutputStream();
zipOutputStream = new ZipOutputStream(bos);
packageZipStream("0011", zipOutputStream);
} catch (Exception e) {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
try {
ServletOutputStream os = response.getOutputStream();
os.write(e.getMessage().getBytes());
os.flush();
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {
// 注意: 像这种一层套一层的包装流,关闭顺序一定是先关闭外层包装流,然后再关闭内层的流,否则会文件损坏,而且在关闭外层流的时候会报流已经关闭异常
if (zipOutputStream != null) {
try {
zipOutputStream.close();
} catch (Exception e) {
System.out.println("zip输出流关闭异常");
}
}
if (bos != null) {
try {
bos.close();
} catch (Exception e) {
System.out.println("流关闭异常");
}
}
}
// 2. 响应数据
try {
response.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(outName, "UTF-8"));
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(bos.toByteArray());
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载到服务器本地文件夹
* @param response
*/
@GetMapping("/downloadLoc")
public void downloadLoc(HttpServletResponse response) {
FileOutputStream fis = null;
ZipOutputStream zipOutputStream = null;
try {
File file = new File("D:\\Compressed\\my.zip");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();
}
fis = new FileOutputStream(file);
zipOutputStream = new ZipOutputStream(fis);
packageZipStream("0011", zipOutputStream);
} catch (Exception e) {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
try {
ServletOutputStream os = response.getOutputStream();
os.write(e.getMessage().getBytes());
os.flush();
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {
if (zipOutputStream != null) {
try {
zipOutputStream.close();
} catch (Exception e) {
System.out.println("流关闭异常");
}
}
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
System.out.println("流关闭异常");
}
}
}
}
/**
* 请求图片服务获取图像并写入到zip输出流中
* @param imgId
* @param zos
*/
private void packageZipStream(String imgId, ZipOutputStream zos) {
String path = null;
try {
if (zos == null || imgId == null) {
return;
}
// 1. 向zip输出流写入文件(ZipEntry), 如果有多个就循环下面五行代码。 注意: 如果文件重名,会ZipOutputStream会抛出ZipException
path = imgId + File.separator + "正面.jpg";
zos.putNextEntry(new ZipEntry(path));
// 获取要写入ZipEntry的内容
byte[] data = downloadImageFromURL("http://localhost:8098/chat-server/test/getImage?imgType=F");
zos.write(data, 0, data.length);
zos.closeEntry();
path = imgId + File.separator + "反面.jpg";
zos.putNextEntry(new ZipEntry(path));
data = downloadImageFromURL("http://localhost:8098/chat-server/test/getImage?imgType=B");
zos.write(data, 0, data.length);
zos.closeEntry();
} catch (Exception e) {
if (e instanceof ZipException) {
throw new RuntimeException(path + "重名,只进行一次下载处理");
} else {
throw new RuntimeException(e.getMessage());
}
}
}
/**
* java HttpURLConnection作为客户端下载图像
* @param urlPath
* @return
*/
private byte[] downloadImageFromURL(String urlPath) {
HttpURLConnection conn = null;
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
URL url = new URL(urlPath);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(6000);
conn.setDoInput(true);
is = conn.getInputStream();
if (conn.getResponseCode() == 200) {
// 读取响应的输入流到字节输出流
byte[] buff = new byte[1024];
int len = -1;
while ((len = is.read(buff)) != -1) {
bos.write(buff, 0, len);
}
bos.flush();
data = bos.toByteArray();
BASE64Decoder decoder = new BASE64Decoder();
data = decoder.decodeBuffer(new String(data));
} else {
data = null;
}
} catch (Exception e) {
throw new RuntimeException("连接服务器异常");
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return data;
}`
标签:java,zip,bos,try,catch,new,null,response,下载
From: https://www.cnblogs.com/chevalyang/p/18195681