先放一张自己喜欢的图片,写着有劲。
——需求:
简单的说下需求,下载多个文件,并按照自定义的需求把文件放在不同文件夹下,并自定义每个文件的名称,
1.数据库
只说重点两个字段。
name,是在页面上显示的文件的名字。
document_url,是此文件存在于你的硬盘上真实的文件名,我是以UUID命名的。
数据库
2.实现类
这一步,是我项目的具体需求,不重要,重要的就是要凑成一个 Map ,也就是我下面的注释部分是主要的。
/**
*自恋一下
* 汤氏多文件下载
* @param ids
* 组合一个Map<String, Map<String,File>> files
* 第一层 map 的 key 为最外层的文件夹的名字,
* 第二层 map 的 key 为这个文件的自定义路径,如:最外层文件夹/文件夹A/文件夹A1/文件.jpg,
* zip打包后会自动分层。
* 第二层的 value 是真实存在的文件
*/
@Override
public void tangDownloadFiles(List<Long> ids,HttpServletResponse response) {
List<PlanDocumentRecordsEntity> list = queryFactory.selectFrom(qPlanDocumentRecords).where(qPlanDocumentRecords.deleteStatus.eq(1).and(qPlanDocumentRecords.id.in(ids)).and(qPlanDocumentRecords.catalogOrFile.eq(2))).fetch();
//存放文件及其文件的父路径
Map<String,File> fileMap = new HashMap<>();
for (PlanDocumentRecordsEntity entitie : list){
String str = entitie.getDocumentUrl();
String s = "";
if (entitie.getParentId()!=0){
String url = this.getParentName(entitie.getParentId(),s)+str;
File file = new File(upLoadFilePath+str);
fileMap.put(url,file);
}
}
Map<String, Map<String,File>> files = new HashMap<>();
String planName = "计划";
if (ids!=null && ids.size()>0){
//文件件的最外层为此计划的名字
planName = queryFactory.select(qPlanInfo.name).from(qPlanInfo).leftJoin(qPlanDocumentRecords).on(qPlanDocumentRecords.planId.eq(qPlanInfo.id)).where(qPlanDocumentRecords.id.eq(ids.get(0))).fetchFirst();
}
files.put(planName,fileMap);
//开始打包
this.zipMultipleFiles(files,response);
}
其实也是参考的网上别人的写的,但是找不到那个链接了,就不加了
然后我是根据自己的需求所改动了一下。
以下为重要部分。
public void zipMultipleFiles(Map<String, Map<String,File>>files, HttpServletResponse response) {
//下载的压缩包的名
String downloadFilename = UUID.randomUUID().toString().replace("-", "");
System.out.println(downloadFilename);
ZipOutputStream zos = null;
InputStream in = null;
try {
response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);// 设置在下载框默认显示的文件名
downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");
zos = new ZipOutputStream(response.getOutputStream());
for (Map.Entry<String, Map<String,File>> entry : files.entrySet()) {
if (entry.getValue()!=null&&entry.getValue().size()!=0) {
//开始循环
for (Map.Entry<String,File> fileEntry : entry.getValue().entrySet()){
String key = fileEntry.getKey();
int i =key.lastIndexOf("/");
if (i==-1){
i=0;
}
//此 url 是自己组合的在zip包内的该文件的目录结构,不包括最外层的文件夹,因为最外层的文件夹,是我自己固定好的,也就是下载完的压缩包解压后会有一个固定的最外层的文件夹。(注意并不是文件在硬盘上的实际目录结构,实际的所有的文件都放在了同一个文件夹下了)
String url = fileEntry.getKey().substring(0,i);
//自定义压缩包内每个文件的名字
//这步就是要把文件换成自己想要展示出来的名字,也就是上边数据库中 name 字段。
String newFileName = queryFactory.select(qPlanDocumentRecords.name).from(qPlanDocumentRecords).where(qPlanDocumentRecords.documentUrl.eq(fileEntry.getValue().getName())).fetchFirst();
//打压缩包
//entry.getKey()就是上述所说的最外层的文件夹,也是自己定义的。
zos.putNextEntry(new ZipEntry(
entry.getKey()+File.separator+ url + File.separator + newFileName));
//文件路径放入流
in = new FileInputStream(fileEntry.getValue().getPath());
byte[] buffer = new byte[1024];
int r = 0;
while ((r = in.read(buffer)) != -1) {
zos.write(buffer, 0, r);
}
in.close();
}
zos.flush();
}
}
} catch (Exception e) {
log.error("zipFiles error!!", e);
} finally {
if (zos!=null) {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
zos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in!=null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
网友评论