批量下载
适用场景
@RestController
@Api(tags = "ExportController")
@RequestMapping("/export")
@Validated
@AllArgsConstructor
@Slf4j
public class ExportController {
private final ArchivalFileMapService archivalFileMapService;
private final ExportService exportService;
private final DataService dataService;
/**
* 按档号导出,以档号为文件夹名称
* <br/>
*
* @param archivalCode
* @param httpResponse
* @return com.hzzl.erms.archival.common.api.CommonResult<?>
*/
@ApiOperation(value = "按档号导出文件")
@RequestMapping(value = "/archival", method = RequestMethod.GET)
@SneakyThrows
public void exportInfoAuto(@RequestParam @NotBlank String archivalCode, HttpServletResponse httpResponse) {
log.info("exportInfoAuto() called with parameters => 【archivalCode = {}】", archivalCode);
// 查询档号对应的文件列表
List<ArchivalFileMap> archivalFileMaps = archivalFileMapService.selectByArchivalCode(archivalCode);
Assert.notEmpty(archivalFileMaps);
//生成Excel文件 archivalTmp
String excelPath =
StrUtil.builder().append(PathUtil.excelPath()).append(archivalCode).append(".xlsx").toString();
File excel = FileUtil.newFile(excelPath);
//待导出的条目数据
List<ExportEntity> list = new ArrayList<>();
list = generateMockData();
exportService.exportList(list, includedColumnFields(), excelPath);
// 用于存储所有需要下载的文件
List<SysFile> listFile =
archivalFileMaps.stream().map(a -> {
SysFile fileInfo = archivalFileMapService.getFileInfo(a.getUuid());
Assert.notNull(fileInfo);
return fileInfo;
}).collect(Collectors.toList());
// 以当前日期作为 zip 压缩包的名称
String zipName = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now()) + ".zip";
// 清空输出流
httpResponse.reset();
httpResponse.setCharacterEncoding("UTF-8");
// 注意写法,避免中文乱码
httpResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipName, "UTF-8"));
httpResponse.setContentType("application/x-msdownload");
@Cleanup
BufferedOutputStream bos = null;
bos = new BufferedOutputStream(httpResponse.getOutputStream());
@Cleanup
ZipOutputStream out = new ZipOutputStream(bos);
//把Excel放入压缩包
ZipEntry excelEntry = new ZipEntry(excel.getName());
out.putNextEntry(excelEntry);
out.write(FileUtil.readBytes(excel));
Assert.notEmpty(listFile);
for (SysFile sysFile : listFile) {
Assert.notNull(sysFile.getUrl());
// 对url进行预处理后,使用 Hutool 工具类下载
HttpResponse res = HttpRequest.get(UrlEncodeUtil.reformatUrl(sysFile.getUrl())).execute();
InputStream object = res.bodyStream();
byte[] buf = new byte[1024];
int length = 0;
String strDirectoryLevel =
StrUtil.builder()
.append(archivalCode)
.append(PathUtil.separator())
.append(sysFile.getName())
.toString();
final ZipEntry zipEntry = new ZipEntry(strDirectoryLevel);
out.putNextEntry(zipEntry);
while ((length = object.read(buf)) > 0) {
out.write(buf, 0, length);
}
}
out.close();
bos.close();
FileUtil.del(excel);
}
}
public class UrlEncodeUtil {
// 防止url中有中文出现异常
@SneakyThrows
public static String reformatUrl(String url) {
List<String> list = StrUtil.split(url, "/");
String tmp = list.get(list.size() - 1);
URLEncoder.encode(tmp, "UTF-8");
String urlTmp = StrUtil.subBefore(url, "/", true).toString() + "/" + tmp;
url = StrUtil.builder().append(urlTmp).toString();
return url;
}
}
重构一下
@ApiOperation(value = "按档号导出文件")
@RequestMapping(value = "/archival", method = RequestMethod.GET)
@SneakyThrows
public void exportInfoAuto(@RequestParam @NotBlank String archivalCode, HttpServletResponse httpResponse) {
log.info("exportInfoAuto() called with parameters => 【archivalCode = {}】", archivalCode);
// 查询档号对应的文件列表
List<ArchivalFileMap> archivalFileMaps = archivalFileMapService.selectByArchivalCode(archivalCode);
Assert.notEmpty(archivalFileMaps);
//生成Excel文件 archivalTmp
String excelPath =
StrUtil.builder().append(PathUtil.excelPath()).append(archivalCode).append(".xlsx").toString();
File excel = FileUtil.newFile(excelPath);
//待导出的条目数据
List<ExportEntity> list = new ArrayList<>();
list = generateMockData();
exportService.exportList(list, includedColumnFields(), excelPath);
// 用于存储所有需要下载的文件
List<SysFile> listFile =
archivalFileMaps.stream().map(a -> {
SysFile fileInfo = archivalFileMapService.getFileInfo(a.getUuid());
Assert.notNull(fileInfo);
return fileInfo;
}).collect(Collectors.toList());
// 以当前日期作为 zip 压缩包的名称
String zipName = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now()) + ".zip";
// 设置返回信息的元信息
setResponseHeaderMeta(httpResponse, zipName);
@Cleanup
BufferedOutputStream bos = null;
bos = new BufferedOutputStream(httpResponse.getOutputStream());
@Cleanup
ZipOutputStream out = new ZipOutputStream(bos);
//把Excel放入压缩包
ZipEntry excelEntry = new ZipEntry(excel.getName());
out.putNextEntry(excelEntry);
out.write(FileUtil.readBytes(excel));
Assert.notEmpty(listFile);
for (SysFile sysFile : listFile) {
Assert.notNull(sysFile.getUrl());
//构造目录层级
String strDirectoryLevel =
StrUtil.builder()
.append(archivalCode)
.append(PathUtil.separator())
.append(sysFile.getName())
.toString();
final ZipEntry zipEntry = new ZipEntry(strDirectoryLevel);
out.putNextEntry(zipEntry);
// 对url进行预处理后,使用 Hutool 工具类下载
out.write(HttpUtil.downloadBytes(UrlEncodeUtil.reformatUrl(sysFile.getUrl())));
}
out.close();
bos.close();
FileUtil.del(excel);
}
@SneakyThrows
private void setResponseHeaderMeta(HttpServletResponse httpResponse, String fileName) {
// 清空输出流
httpResponse.reset();
httpResponse.setCharacterEncoding("UTF-8");
// 注意写法,避免中文乱码
httpResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
httpResponse.setContentType("application/x-msdownload");
}