Java实现批量打包文件Zip下载(适用于Windows,Linux)
2.Service层3.批量下载,zip打包效果(示例:Windows版,linux也一样)
前言
1.思路总结:
* 1.每个单号多个文件直接遍历IO临时单号zip包,
* 2.多个单号临时zip包遍历IO到总临时zip包,
* 3.总临时zip包copy到前端下载zip包,
* 4.删除所有临时zip包,下载完成!
2. 参数说明:
* AcasConfig.getProfile() 自定义的路径 D:/home/acas/uploadPath
* totalZip:总临时zip包
* zipList:多个临时订单zip包集合
* zipFilePath:当前订单临时zip
* paths:文件路径数组
目录
3.批量下载,zip打包效果(示例:Windows版,linux也一样)
1.RestController层
/**本方法使用windows,Linux 批量下载,zip打包 实测用于生产环境
* 通过订单id批量下载
* @param ids 货号单集合
* @return
* 思路总结:
* 1.每个单号多个文件直接遍历IO临时单号zip包,
* 2.多个单号临时zip包遍历IO到总临时zip包,
* 3.总临时zip包copy到前端下载zip包,
* 4.删除所有临时zip包,下载完成!
* 参数说明:
* AcasConfig.getProfile() 自定义的路径 D:/home/acas/uploadPath
* totalZip:总临时zip包
* zipList:多个临时订单zip包集合
* zipFilePath:当前订单临时zip
* paths:文件路径数组
*/
@Api(tags = "订单表")
@RestController
@RequestMapping("/order/order")
@Slf4j
public class OrderController extends BaseController {
@Autowired
private IOrderService orderService;
@Autowired
private OrderMapper orderMapper;
/**本方法使用windows,Linux 批量下载,zip打包 实测用于生产环境
*
* 通过订单id批量下载
* @param ids 货号单集合
* @return
*
* 思路总结:
* 1.每个单号多个文件直接遍历IO临时单号zip包,
* 2.多个单号临时zip包遍历IO到总临时zip包,
* 3.总临时zip包copy到前端下载zip包,
* 4.删除所有临时zip包,下载完成!
*
* 参数说明:
* AcasConfig.getProfile() 自定义的路径 D:/home/acas/uploadPath
* totalZip:总临时zip包
* zipList:多个临时订单zip包集合
* zipFilePath:当前订单临时zip
* paths:文件路径数组
*/
@ApiOperation(value = "通过订单id批量下载", notes = "通过订单id批量下载")
@GetMapping(value = "/batchDownload")
public AjaxResult batchDownload(@RequestParam String ids, HttpServletResponse response) {
//批量下载订单号单如 ids:"MA2206280160900002,MA2206280003500001,MA2206280003500002,MA2206280003500003"
String[] parameterValues = ids.split(",");
//各个文件压缩包临时存放路径集合
List<String> zipList = new ArrayList();
//Linux版创建临时zip,总存放压缩文件 AcasConfig.getProfile()= D:/home/acas/uploadPath/临时zip.zip
String totalZip = AcasConfig.getProfile() + "/临时zip.zip";
try {
for (String orderNo : parameterValues) {
//通过遍历订单号获取所有这一订单所有数据库中的文件路径 resultOriginFile:"/profile/upload/2022/05/23/85e2fbc8-6a3e-4544-8a88-97b9febb1ddd粗蛋白.jpg,/profile/upload/2022/05/23/e52773f6-7fae-4c36-97c5-b9edfbea2dc3粗脂肪.jpg"
String resultOriginFile = orderMapper.selectOrder(orderNo).getResultOriginFile();
if (StringUtils.isEmpty(resultOriginFile)) {
continue;
}
//Linux版创建临时文件
String zipFilePath = AcasConfig.getProfile() + "/" + orderNo + "订单zip.zip";
zipList.add(zipFilePath);
//文件路径数组 paths :["/profile/upload/2022/05/23/85e2fbc8-6a3e-4544-8a88-97b9febb1ddd粗蛋白.jpg","/profile/upload/2022/05/23/e52773f6-7fae-4c36-97c5-b9edfbea2dc3粗脂肪.jpg"]
String[] paths = resultOriginFile.split(",");
//调用@Service层方法
orderService.batchDownload(totalZip, zipList, zipFilePath, paths);
}
//判断有无订单需要下载文件,没有直接相应前台"没有需要下载的文件!",直接结束方法
if (CollectionUtils.isEmpty(zipList)) {
return AjaxResult.error("没有需要下载的文件!");
}
// 设置Content-Disposition响应头,控制浏览器弹出保存框,若没有此句浏览器会直接打开并显示文件
// 中文名要进行URLEncoder.encode编码,否则客户端能下载但名字会乱码
String orderDocuments = "订单原始记录文件.zip";
String filenames = URLEncoder.encode(orderDocuments, "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + filenames + ";" + "filename*=utf-8''" + filenames);
//该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream inputStream = new FileInputStream(totalZip);
// 如果是SpringBoot框架,在这个路径 需要org.apache.tomcat.util.http.fileupload.IOUtils产品否则,需要自主引入apache的 commons-io依赖
// copy方法为文件复制,在这里直接实现了下载效果
IOUtils.copy(inputStream, outputStream);
inputStream.close();
//下载完成之后,删掉临时zip包
zipList.add(totalZip);
for (String zipListPath : zipList) {
File fileTempZip = new File(zipListPath);
fileTempZip.delete();
}
} catch (Exception e) {
log.error("下载异常!", e);
return AjaxResult.error("下载异常!");
}
return AjaxResult.success("下载完成!");
}
}
2.Service层
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
@Override
public void batchDownload(String totalZip, List<String> zipList, String zipFilePath, String[] paths) throws IOException {
//Linux不会自动创建,手动创建临时的.zip文件
File totalFile = new File(totalZip);
if (!totalFile.exists()) {
totalFile.createNewFile();
}
File zipFile = new File(zipFilePath);
if (!zipFile.exists()) {
zipFile.createNewFile();
}
if (paths.length != 0) {
//压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
ZipOutputStream totalZipOut = new ZipOutputStream(new FileOutputStream(totalZip));
//循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
for (String path : paths) {
//文件完整路径
String pathFile = path.replaceAll("/profile", "");
path = AcasConfig.getProfile() + pathFile;
//调用压缩方法在下面定义
fileToZip(path, zipOut);
}
zipOut.close();
//循环调用压缩文件方法,将一个一个压缩包打入总压缩文件包
for (String zipListPath : zipList) {
fileToZip(zipListPath, totalZipOut);
}
totalZipOut.close();
}
}
private static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {
// 需要压缩的文件
File file = new File(filePath);
// 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
String documents = 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(documents));
int length = 0;
// 最常规IO操作,不必紧张
while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length);
}
//关闭流
fileInput.close();
// 需要注意的是缓冲流必须要关闭流,否则输出无效
bufferStream.close();
// 压缩流不必关闭,使用完后再关
}
}
3.批量下载,zip打包效果(示例:Windows版,linux也一样)
我也是第一次接触批量下载,它本身并不难,都只是一些IO的常规操作,没有弯弯绕绕,只是在实现完整功能的过程中踩到了一些坑,在此记录一下,以便加深印象和帮助他人吧~~
更多推荐
所有评论(0)