思路:将所需的附件用list 按所需的条件分组,转为Map.遍历map即可。
前端vue 要用blob类型重新封装
vue 前端代码:
// 下载资料
downloadZip(record){
console.log(record);
const issueFormRecordId = record.issueFormRecordId;
if (issueFormRecordId) {
const downUrl = _ctxPath + '/rest/XXXX/downloadIssueAttAchmentZip?issueFormRecordId=' + issueFormRecordId;
this.$http({
method: 'get',
url: downUrl,
responseType: 'blob'
}).then(res => {
console.log(res);
if ('application/octet-stream' !== res.data.type) {
window.ctpTop.$.alert('没有可下载的资料');
return false;
} else {
const nowDate = new Date();
const date = {
year: nowDate.getFullYear(),
month: nowDate.getMonth() + 1,
date: nowDate.getDate()
};
const systemTime = date.year + '' + date.month + '' + date.date;
this.downloadTemplateFile(res.data, '议题资料' + systemTime + '.zip');
}
}).catch(err => {
console.log(err);
});
}
},
downloadTemplateFile(data, fileName) {
//support ie10+
if (window.navigator.msSaveBlob) {
try {
window.navigator.msSaveBlob(new Blob([data]), fileName);
} catch (e) {
console.log(e);
}
} else {
const reader = new FileReader();
reader.readAsDataURL(data);
reader.onload = e => {
const a = document.createElement('a');
a.download = fileName;
a.style.display = 'none';
a.href = e.target.result || '#';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
}
}
后台:
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("downloadIssueAttAchmentZip")
public Response downloadIssueAttAchmentZip(@QueryParam("issueFormRecordId") Long issueFormRecordId) {
if (issueFormRecordId == null) {
return fail(ResourceUtil.getString("conference.info.paramError"));
}
Map attachmentmap;
try {
attachmentmap = conferenceIssueRepositoryManager.getDownloadIssueAttAchment(issueFormRecordId);
} catch (BusinessException e) {
LOGGER.error("BusinessException:", e);
return fail("附件下载失败:" + e.getMessage());
}
if (Objects.isNull(attachmentmap)) {
return fail("无附件信息");
}
//设置最终输出zip文件的目录+文件名
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String zipFileName = ConferenceConstant.AttachmentType.ALL_MATERIALS.getName().concat(formatter.format(new Date())) + ".zip";
// 定义zip输出流
ZipOutputStream zipStream = null;
BufferedInputStream bufferStream = null;
File zipFile = new File(zipFileName);
// 文件是存在
Boolean isContinue = Boolean.FALSE;
//构造最终压缩包的输出流
try {
zipStream = new ZipOutputStream(new FileOutputStream(zipFile));
// 分组文件列表
Map attachmentlistmap = (Map) attachmentmap.get(ConferenceConstant.AttachmentType.ALL_MATERIALS.getValue());
for (Map.Entry attachmentEntry : attachmentlistmap.entrySet()) {
// 分组文件夹名
String folderName = ConferenceConstant.AttachmentType.getAttachmentTypeName(ConferenceParamUtil.getString(attachmentmap.get(ConferenceParamUtil.getLong(attachmentEntry.getKey())))).getName();
// 单组文件列表
List attachmentList = attachmentEntry.getValue();
if (!CollectionUtils.isEmpty(attachmentList) && !ConferenceConstant.AttachmentType.OTHER_MATERIALS.getName().equals(folderName)) {
isContinue = Boolean.TRUE;
// 遍历分组值列表
for (Attachment attachment : attachmentList) {
// 获取base64存储的数据
String base64Str = FileZipUtil.getContentBits64Content(attachment.getFileUrl());
// 数据为空
if (Strings.isBlank(base64Str)) {
continue;
}
base64Decoder decoder = new base64Decoder();
// base64解码,对字节数组字符串进行base64解码并生成文件
byte[] byt = decoder.decodeBuffer(base64Str);
for (int a = 0, len = byt.length; a < len; ++a) {
// 调整异常数据
if (byt[a] < 0) {
byt[a] += 256;
}
}
InputStream input = new ByteArrayInputStream(byt);
ZipEntry zipEntry = new ZipEntry("\" + folderName + "\" + attachment.getFilename());
zipStream.putNextEntry(zipEntry);
bufferStream = new BufferedInputStream(input, 1024 * 10);
int read = 0;
byte[] buf = new byte[1024 * 10];
while ((read = bufferStream.read(buf, 0, 1024 * 10)) != -1) {
zipStream.write(buf, 0, read);
}
}
}
}
} catch (Exception e) {
LOGGER.error("Exception:", e);
return fail("附件下载失败:同一个文件夹下存在多个文件名相同的文件" + e.getMessage());
} finally {
//关闭流
try {
if (null != bufferStream) {
bufferStream.close();
}
if (null != zipStream) {
zipStream.flush();
zipStream.close();
}
} catch (IOException e) {
LOGGER.error("IOException:", e);
}
}
//判断系统压缩文件是否存在:true-把该压缩文件通过流输出给客户端后删除该压缩文件 false-未处理
if (zipFile.exists() && isContinue) {
// 调用下载方法
FileZipUtil.groupDownZip(resp, zipFileName);
zipFile.delete();
}
return success(null);
}
public static void groupDownZip(HttpServletResponse response, String zipFileName) {
if (zipFileName != null) {
FileInputStream inputStream = null;
BufferedInputStream bufferedInputStream = null;
OutputStream outputStream = null;
try {
File file = new File(zipFileName);
if (file.exists()) {
//设置Headers
response.setHeader("Content-Type", "application/octet-stream");
//设置下载的文件的名称-该方式已解决中文乱码问题
response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(zipFileName, "UTF-8").getBytes(), "utf-8"));
inputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(inputStream);
outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int lenth = 0;
while ((lenth = bufferedInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, lenth);
}
} else {
LOGGER.error("下载失败,文件内容为空");
}
} catch (IOException ex) {
LOGGER.error("IOException,文件内容为空" + ex.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
LOGGER.error("IOException,printStackTrace" + e.getMessage());
}
}
}
}
public static String getContentBits64Content(Long fileId) {
String textContent = "";
//根据文件Id,获得文件对象
File file;
try {
file = fileManager.getFile(fileId);
if (file.isFile() && file.exists()) {
//将文件 转换为字符串
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
inputFile.read(buffer);
inputFile.close();
//字符串加密
textContent = new base64Encoder().encode(buffer);
}
} catch (Exception e) {
LOGGER.error("读取文件内容报错", e);
}
return textContent.replaceAll(System.getProperty("line.separator"), "");
}



