最近项目有需求,需要把管理中的数据,按照ID下载其附件,但由于附件较多,因此需要用压缩包的形式下载。
我们的文件都采用相对路径存储在远程FTP服务器。因此需要连接远程FTP服务器(正式环境存储在OSS服务器)
需要用到的对象如下:ZipOutputStream ,ZipEntry
ZipOutputStream下有多个ZipEntry。就像一个纸盒子里面有很多饼干,糖果等等。纸盒子就是输出流ZipOutputStream,饼干和糖果就是ZipEntry。商店把饼干和糖果装进(putNextEntry)纸盒子里系好然后卖给你
理解了概念,代码直接贴出来了。
代码如下:
步骤一:取数,得到文件名
/**
* 【下载附件】报价记录/报名记录
* @param id
*/
@GetMapping("/download/{id}")
public void downloadAnnex(@PathVariable("id") Long id) {
BiddingRecordDto brDto = biddingRecordFacede.getById(id);
if(null == brDto){
log.error("{}",brDto.toString());
throw new CustomTipException("未查询到报价信息!");
}
List<String> imageAnnexs = new ArrayList<>();
List<String> fileAnnexs = new ArrayList<>();
if(!StringUtils.isEmpty(brDto.getImageAnnex())){
imageAnnexs = JSONArray.parseArray(brDto.getImageAnnex()).toJavaList(String.class);
}
if(!StringUtils.isEmpty(brDto.getFileAnnex())){
fileAnnexs = JSONArray.parseArray(brDto.getFileAnnex()).toJavaList(String.class);
}
List<String> unionList = new ArrayList<>();
if(!CollectionUtils.isEmpty(imageAnnexs)){
unionList.addAll(imageAnnexs);
}
if(!CollectionUtils.isEmpty(fileAnnexs)){
unionList.addAll(fileAnnexs);
}
log.info(imageAnnexs.toString()+"\n"+fileAnnexs.toString());
String fileName = UUID.randomUUID().toString();
exportToBrowser(browsePath,fileName+".zip",unionList,response,request);
}
步骤二:导出ZIP,输出到浏览器
/**
* 导出zip文件,输出到浏览器
*/
public static void exportToBrowser(String browsePath,String fileName, List<String> annexPaths, HttpServletResponse response, HttpServletRequest request) {
try {
// 浏览器处理乱码问题
String userAgent = request.getHeader("User-Agent");
// filename.getBytes("UTF-8")处理safari的乱码问题
byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8");
// 各浏览器基本都支持ISO编码
fileName = new String(bytes, "ISO-8859-1");
// 文件名外的双引号处理firefox的空格截断问题
response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
response.setContentType("application/x-msdownload");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
doZIP(browsePath,annexPaths, response);
} catch (Exception e) {
log.info("下载失败!" + e);
}
}
步骤三:打包成压缩包
/**
* 压缩文件
* @param browsePath 文件存储服务器路径
* @param annexPaths 文件名称
* @param response
* @throws IOException
*/
public static void doZIP(String browsePath,List<String> annexPaths,HttpServletResponse response) throws IOException{
InputStream input = null;
//定义压缩输出流
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
for (String fileName : annexPaths) {
//拼接相对路径成绝对路径
String AnnexPath = browsePath+fileName;
URL url = new URL(AnnexPath);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
input = connection.getInputStream();
//压缩包中的子条目
int i = fileName.lastIndexOf("/")+1;
String name = fileName.substring(i);
ZipEntry zipEntry = new ZipEntry(name);
zipOut.putNextEntry(zipEntry);
int len = 0;
byte[] buffer = new byte[1024];
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
}
zipOut.closeEntry();
zipOut.close();
}