基本逻辑 :将mongo文件读取到GridFsResource 转成输入流 用输出流写到本地 然后 读取本地文件 用ZipOutputStream 进行压缩 然后 输出到浏览器 删除 本地的 文件和压缩包
void downloadZipByMongodb(TtxSession sess, HttpServletRequest request, HttpServletResponse response)
throws Exception {
String ids = "23.jpg,23.pdf"
List<String> paths = new ArrayList<>()
String filePath = "D:\\test\\zip"
// String filePath = request.getSession().getServletContext().getRealPath("");
String[] idList = ids.split(",")
/* 循环从mongodb下载文件*/
for (String id : idList) {
List<GridFSFile> gfsFile = mongoService.gridfsFindFileByName(sess.db, "files", id)?.collect({ it })
if (gfsFile && gfsFile.size() > 0) {
OutputStream os = new ByteArrayOutputStream()
mongoService.gridfsDownloadToStream(sess.db, "files", gfsFile[0].objectId, os)
byte[] buffer = os.toByteArray()
InputStream sbs = new ByteArrayInputStream(buffer)
GridFsResource gridFsResource =
new GridFsResource(
gfsFile[0],sbs
)
String fileName = gfsFile[0].getFilename().replace(",", "")
// 处理中文文件名乱码
if (request.getHeader("User-Agent").toUpperCase().contains("MSIE")
|| request.getHeader("User-Agent").toUpperCase().contains("TRIDENT")
|| request.getHeader("User-Agent").toUpperCase().contains("EDGE")) {
fileName = java.net.URLEncoder.encode(fileName, "UTF-8")
} else {
// 非IE浏览器的处理:
fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8)
}
String newfilePath = filePath + File.separator + fileName
paths.add(newfilePath)
File file = new File(newfilePath)
copyInputStreamToFile(gridFsResource.getInputStream(), file)
}
}
plistDownLoad(paths,filePath, response)
}
private static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException {
FileOutputStream outputStream = new FileOutputStream(file)
int read
byte[] bytes = new byte[1024]
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read)
}
outputStream.close()
}
/** 批量压缩并下载 */
void plistDownLoad(List<String> paths,String filePath , HttpServletResponse response) throws Exception {
if (paths.size() != 0) {
// 创建临时路径,存放压缩文件
String zipFilePath = filePath + File.separator + "label.zip"
// 压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包
ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(Paths.get(zipFilePath)))
// 循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
for (String path : paths) {
// 该方法在下面定义
fileToZip(path, zipOut)
}
// 压缩完成后,关闭压缩流
zipOut.close()
// 拼接下载默认名称并转为ISO-8859-1格式
String fileName = new String(("label.zip").getBytes(), StandardCharsets.UTF_8)
response.setHeader("Content-Disposition", "attachment;filename=" + fileName)
// 该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
ServletOutputStream outputStream = response.getOutputStream()
FileInputStream inputStream = new FileInputStream(zipFilePath)
// 如果是SpringBoot框架,在这个路径
// org.apache.tomcat.util.http.fileupload.IOUtils产品
// 否则需要自主引入apache的 commons-io依赖
// copy方法为文件复制,在这里直接实现了下载效果
IOUtils.copy(inputStream, outputStream)
// 关闭输入流
inputStream.close()
outputStream.close()
// 下载完成之后,删掉这个zip包
File fileTempZip = new File(zipFilePath)
fileTempZip.delete()
/*循环删除输出到本地的文件*/
for (String path : paths) {
File file = new File(path)
file.delete()
}
}
}
/** 单个文件压缩进zip文件 */
static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {
// 需要压缩的文件
File file = new File(filePath)
// 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
String fileName = file.getName()
FileInputStream fileInput = new FileInputStream(filePath)
// 缓冲
byte[] bufferArea = new byte[1024 * 10]
BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10)
// 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
zipOut.putNextEntry(new ZipEntry(fileName))
int length = 0
// 最常规IO操作
while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length)
}
// 关闭流
fileInput.close()
// 需要注意的是缓冲流必须关闭掉,否则输出无效
bufferStream.close()
// 压缩流不必关闭,使用完后再关
}
GridFsResource 包 compile "org.springframework.boot:spring-boot-starter-data-mongodb:1.6.1"
可参考 https://blog.csdn.net/qq_37010513/article/details/127967555