需求:前端发送一个表单 id,根据表单 id 查询出数据库中全部相关附件(数据库存储了附件url,格式为https://xxx),将附件打包为zip后返回前端浏览器下载
分析:
1、根据 id 获取到全部文件,使用 URL 类的 openStream() 方法,获取 url 路径中文件的输出流
2、创建一个 ByteArrayOutputStream 对象,作为参数传递到 ZipOutputStream 对象的构造器中,使用 ZipOutputStream 的 write() 方法,将url 路径中文件的输出流数据流写入到 ByteArrayOutputStream 流中
3、将 ByteArrayOutputStream 对象转化为字节数组,再将字节数组写入到 ServletOutputStream 中,之后再返回给前端
示例代码:
/**
* 文件下载 Controller 层
* @param id
* @param response
* @return
*/
@AutoLog(value = "下载文件")
@GetMapping(value = "/downFile")
public Wrapper<?> downFile(String id, HttpServletResponse response) {
optimalFileService.download(id, response);
}
/**
* 文件下载 Service 层
* @param id
* @param response
*/
public void download(String id, HttpServletResponse response) {
if (StringUtils.isNotEmpty(id)) {
List<OptimalFile> optimalFileList = this.list(new LambdaQueryWrapper<OptimalFile>().eq(OptimalFile::getRelevanceId, id));
InputStream inputStream = null;
// 创建一个ByteArrayOutputStream对象,用于接收文件流数据
ByteArrayOutputStream baos = null;
ZipOutputStream zipOut = null;
ServletOutputStream outputStream = null;
try {
baos = new ByteArrayOutputStream();
// ByteArrayOutputStream 对象作为 ZipOutputStream 构造器参数传入
// ZipOutputStream 写入的数据会存储到 ByteArrayOutputStream 中
zipOut = new ZipOutputStream(baos);
for (int i = 0; i < optimalFileList.size(); i++) {
// 将数据库文件的 url 字符串转化为 URL 对象之后,获取文件输入流
inputStream = new URL(optimalFileList.get(i).getUrl()).openStream();
// 往 ZipOutputStream 中添加文件
zipOut.putNextEntry(new ZipEntry(i + 1 + "、" + optimalFileList.get(i).getFileName()));
int len;
byte[] buf = new byte[1024];
// 将输入流的数据写入输出流中
while ((len = inputStream.read(buf)) != -1) {
zipOut.write(buf, 0, len);
}
zipOut.closeEntry();
}
// 完成压缩
zipOut.finish();
// 将 ByteArrayOutputStream 转化为字节数组
byte[] zipBytes = baos.toByteArray();
// 设置 HttpServletResponse
String fileName = URLEncoder.encode("附件下载.zip", "UTF-8");
response.setCharacterEncoding("utf-8");
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;FileName=" + fileName);
// 获取响应输出流
outputStream = response.getOutputStream();
// 写入内容
outputStream.write(zipBytes);
// 将响应缓冲区内容发送至客户端
response.flushBuffer();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// 关闭流资源
try {
if (outputStream != null) {
outputStream.close();
}
if (baos != null) {
baos.close();
}
if (zipOut != null) {
zipOut.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}