最近项目中遇到关于客户档案管理的需求,其中的下载需求如下:
1. 单个文件直接下载,多个文件下载自动打zip包。
2. 下载的zip包中保留指定的目录结构(目录结构自定义)
后端代码分享如下:
1. controller层:
@PostMapping("/download")
public void downLoadFile(DownloadParams downloadParams, HttpServletResponse response) {
//多个文件下载url,用 ,分隔的
logger.info("下载文档url:{}", downloadParams.getFileKeys());
if (StringUtils.isNotBlank(downloadParams.getFileKeys())) {
List<String> fileKeys = new ArrayList<>(Arrays.asList(downloadParams.getFileKeys().split(",")));
response.setContentType("application/octet-stream;charset=utf-8");
if (fileKeys.size() == 1) {
String fileUrl = fileKeys.get(0);
String[] arr = fileUrl.split("/");
String fileName = arr[arr.length - 1].split("\\?")[0];
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
try {
downloadService.downloadFile(fileUrl, response.getOutputStream());
} catch (IOException e) {
logger.info("下载文档失败,e:{}", e);
throw new BadRequestAlertException("文件下载失败,请联系管理员!", "download", "error");
}
} else {
//多文档下载,以zip包形式下载
String zipFileName = System.currentTimeMillis()+".zip";
response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);
try {
downloadService.downloadZipPackage(fileKeys, response.getOutputStream());
} catch (IOException e) {
logger.error("批量下载客户文档出错 error:{}", e);
throw new BadRequestAlertException("批量下载异常,请联系管理员!", "", "error");
}
}
} else {
throw new BadRequestAlertException("未选择任何待下载文件,请先勾选待下载文件!", "", "error");
}
}
2. DownloadServiceImpl的代码:
@Service
public class DownLoadServiceImpl implements DownloadService {
private final Logger logger = LoggerFactory.getLogger(BussinessInfoServiceImpl.class);
@Override
public void downloadFile(String fileUrl, OutputStream out) {
URLConnection conn = null;
try {
URL url = new URL(fileUrl);
conn = url.openConnection();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
if (conn != null) {
try (InputStream inStream = conn.getInputStream()) {
int len;
byte[] buffer = new byte[1024];
while ((len = inStream.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
@Override
public void downloadZipPackage(List<String> fileUrls, OutputStream out) throws IOException {
//将输出流转换成Zip输出流
ZipOutputStream zos = new ZipOutputStream(out);
List<String> fileNames = new ArrayList<>();
for (String fileUrl : fileUrls) {
//根据Url获取文件名
String[] arr = fileUrl.split("/");
String fileName = arr[arr.length - 1].split("\\?")[0];
if (fileNames.contains(fileName)) {
//如果文件有重名,会自动修改文件名,防止打包出错
fileName = System.currentTimeMillis() + fileName;
}
fileNames.add(fileName);
//这里的目录结构只是举例,可以是任何目录,相同目录前缀的文件将会被放在一起,不同的就会分开存放
StringBuilder dirName = new StringBuilder("一级目录/").append("二级目录/").append("三级目录");
fileName = dirName.toString() + File.separator + fileName;
URL url = new URL(fileUrl);
zos.putNextEntry(new ZipEntry(fileName));
URLConnection httpConn = url.openConnection();
//获取文件的网络输入流
InputStream fis = httpConn.getInputStream();
byte[] buffer = new byte[1024];
int r;
while ((r = fis.read(buffer)) != -1) {
zos.write(buffer, 0, r);
}
fis.close();
}
zos.flush();
zos.close();
}
}
功力有限,代码有写的不好的地方,欢迎大家指教!