压缩下载
This commit is contained in:
parent
6388a84432
commit
9d503f89e3
|
|
@ -35,7 +35,7 @@ public class DownloadController {
|
|||
|
||||
@PostMapping("/start")
|
||||
public ResponseEntity<String> startDownload(@RequestBody DownloadRequest request) {
|
||||
downloadService.startDownloadTask(request.getTaskId(), request.getProId(),request.getType());
|
||||
downloadService.startDownloadTask(request.getTaskId(), request.getProId(),request.getType(),request.getProName());
|
||||
return ResponseEntity.ok("Download task started");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ public interface SynthesisQueryDao {
|
|||
|
||||
/**
|
||||
* 查询原图/水印照片
|
||||
*
|
||||
* @param proId
|
||||
* @param type
|
||||
* @return List<String>
|
||||
|
|
@ -121,4 +122,14 @@ public interface SynthesisQueryDao {
|
|||
* @date 2025/4/7 10:59
|
||||
*/
|
||||
List<Photo> findByAlbumId(@Param("proId") String proId, @Param("type") String type);
|
||||
|
||||
/**
|
||||
* 添加下载任务
|
||||
* @param taskId
|
||||
* @param nowTime
|
||||
* @return void
|
||||
* @author cwchen
|
||||
* @date 2025/4/8 9:37
|
||||
*/
|
||||
void addTaskDownload(@Param("taskId") String taskId, @Param("nowTime") String nowTime,@Param("filePath") String filePath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ public class DownloadRequest {
|
|||
private String taskId;
|
||||
private String proId;
|
||||
private String type;
|
||||
private String proName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ import lombok.Data;
|
|||
@Data
|
||||
public class Photo {
|
||||
private String photoId;
|
||||
private String albumId;
|
||||
private String filePath;
|
||||
private String uploadType;
|
||||
private String uploadTypeName;
|
||||
private String sourceTypeName;
|
||||
private String title;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.bonus.imgTool.backstage.service;
|
|||
import com.bonus.imgTool.backstage.dao.SynthesisQueryDao;
|
||||
import com.bonus.imgTool.backstage.entity.Photo;
|
||||
import com.bonus.imgTool.backstage.entity.ProClassifyStatisticDetailVo;
|
||||
import com.bonus.imgTool.utils.DateTimeHelper;
|
||||
import com.bonus.imgTool.utils.SystemUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -52,13 +53,13 @@ public class DownloadService {
|
|||
private final Map<String, String> taskFileMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Async
|
||||
public void startDownloadTask(String taskId, String proId,String type) {
|
||||
public void startDownloadTask(String taskId, String proId,String type,String proName) {
|
||||
Path tempDirPath = null;
|
||||
try {
|
||||
// 准备临时目录
|
||||
tempDirPath = Paths.get(tempDir, taskId);
|
||||
Files.createDirectories(tempDirPath);
|
||||
Path zipFilePath = tempDirPath.resolve("photos.zip");
|
||||
Path zipFilePath = tempDirPath.resolve(proName + ".zip");
|
||||
// 获取照片列表
|
||||
List<Photo> photos = getPhotosForAlbum(proId,type);
|
||||
int total = photos.size();
|
||||
|
|
@ -71,10 +72,12 @@ public class DownloadService {
|
|||
for (Photo photo : photos) {
|
||||
String path = SystemUtils.getUploadPath() + File.separator + photo.getFilePath();
|
||||
Path photoPath = Paths.get(path);
|
||||
String uniqueEntryName = "photos/" + photo.getPhotoId() + "_" + photoPath.getFileName();
|
||||
if (!Files.exists(photoPath)) { // 文件不存在
|
||||
continue;
|
||||
}
|
||||
String uniqueEntryName = handlePath(proName,photo,photoPath);
|
||||
ZipEntry entry = new ZipEntry(uniqueEntryName);
|
||||
zos.putNextEntry(entry);
|
||||
|
||||
try (InputStream is = Files.newInputStream(photoPath)) {
|
||||
int len;
|
||||
while ((len = is.read(buffer)) > 0) {
|
||||
|
|
@ -90,17 +93,18 @@ public class DownloadService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动到输出目录
|
||||
Path outputDirPath = Paths.get(outputDir);
|
||||
Files.createDirectories(outputDirPath);
|
||||
Path finalFilePath = outputDirPath.resolve(taskId + ".zip");
|
||||
Files.move(zipFilePath, finalFilePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
// 记录文件位置
|
||||
taskFileMap.put(taskId, finalFilePath.toString());
|
||||
// 通知完成
|
||||
notifyComplete(taskId, "/imgTool/api/download/file?taskId=" + taskId);
|
||||
// 添加下载任务
|
||||
String nowTime = DateTimeHelper.currentTwoHours();
|
||||
synthesisQueryDao.addTaskDownload(taskId,nowTime,finalFilePath.toString());
|
||||
} catch (Exception e) {
|
||||
logger.error("下载任务失败: " + taskId, e);
|
||||
notifyError(taskId, "文件生成失败: " + e.getMessage());
|
||||
|
|
@ -116,6 +120,20 @@ public class DownloadService {
|
|||
}
|
||||
}
|
||||
|
||||
public String handlePath(String proName,Photo photo,Path photoPath){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(proName).append(File.separator);
|
||||
sb.append(photo.getUploadTypeName()).append(File.separator);
|
||||
if(!Objects.equals(photo.getUploadType(),"5")){
|
||||
String[] sourceTypeNameArr = photo.getSourceTypeName().split("-");
|
||||
sb.append(sourceTypeNameArr[1]).append(File.separator);
|
||||
}else{
|
||||
sb.append(photo.getTitle()).append(File.separator);
|
||||
}
|
||||
sb.append(photo.getPhotoId()).append("_").append(photoPath.getFileName());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void addProgressListener(String taskId, DownloadProgressListener listener) {
|
||||
progressListeners.computeIfAbsent(taskId, k -> new CopyOnWriteArrayList<>()).add(listener);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class BnsSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
http.authorizeRequests()
|
||||
.antMatchers("/", "/*.html", "/favicon.ico", "/css/**", "/js/**", "/fonts/**", "/layui/**", "/img/**"
|
||||
, "/webjars/**", "/pages/**","/login",
|
||||
"/statics/**","/websocketServer/**")
|
||||
"/statics/**","/websocketServer/**","/api/download/**")
|
||||
.permitAll().anyRequest().authenticated();
|
||||
http.formLogin().loginProcessingUrl("/login")
|
||||
.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and()
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
package com.bonus.imgTool.task;
|
||||
|
||||
import com.bonus.imgTool.task.dao.DownloadTaskDao;
|
||||
import com.bonus.imgTool.task.entity.DownloadTaskVo;
|
||||
import com.bonus.imgTool.utils.DateTimeHelper;
|
||||
import com.bonus.imgTool.utils.FileUtil;
|
||||
import com.bonus.imgTool.utils.SystemUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.javacrumbs.shedlock.core.SchedulerLock;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description 删除原始记录、检测报告等文件定时任务
|
||||
|
|
@ -38,69 +44,40 @@ public class DeleteFileTask {
|
|||
*/
|
||||
private static final int SCHEDULER_LOCK_MIN = 5 * 60 * 1000;
|
||||
|
||||
@Resource(name = "DownloadTaskDao")
|
||||
private DownloadTaskDao downloadTaskDao;
|
||||
|
||||
/**
|
||||
* 删除原始记录、检测报告等文件定时任务
|
||||
* 使用 cron 表达式指定每天23点,执行一次
|
||||
* 删除文件定时任务
|
||||
* 使用 cron 表达式指定每十分钟,执行一次
|
||||
*/
|
||||
@Scheduled(cron = "0 0 23 * * *")
|
||||
@Scheduled(cron = "0 0/10 * ? * *")
|
||||
@SchedulerLock(name = "StationMonthTask", lockAtMostFor = SCHEDULER_LOCK_MAX, lockAtLeastFor = SCHEDULER_LOCK_MIN)
|
||||
@Async
|
||||
public void getHomeCacheTask() {
|
||||
log.info("--------删除原始记录、检测报告等文件定时任务开启------");
|
||||
// 当前日期
|
||||
String nowDate = DateTimeHelper.getNowDate();
|
||||
// 删除该日期之前的文件夹
|
||||
deleteFoldersBeforeDate(nowDate);
|
||||
log.info("--------删除原始记录、检测报告等文件定时任务执行完毕------");
|
||||
}
|
||||
|
||||
// 删除指定目录下所有在当前日期之前的文件夹
|
||||
public static void deleteFoldersBeforeDate(String nowDate) {
|
||||
File dir = new File(SystemUtils.getUploadPath());
|
||||
if (!dir.exists() || !dir.isDirectory()) {
|
||||
log.warn("指定的目录不存在或不是一个目录:" + SystemUtils.getUploadPath());
|
||||
return;
|
||||
}
|
||||
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
log.info("--------删除缓存文件定时任务开启------");
|
||||
try {
|
||||
// 假设文件夹名符合日期格式(yyyy-MM-dd)
|
||||
String folderName = file.getName();
|
||||
Date folderDate = sdf.parse(folderName);
|
||||
Date currentDate = sdf.parse(nowDate);
|
||||
|
||||
if (folderDate.before(currentDate)) {
|
||||
deleteDirectory(file);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
log.error("日期解析失败,文件夹名称可能不符合预期格式:" + file.getName(), e);
|
||||
} catch (Exception e) {
|
||||
log.error("处理文件夹时发生异常:" + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 递归删除文件夹
|
||||
public static void deleteDirectory(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteDirectory(file);
|
||||
List<DownloadTaskVo> list = downloadTaskDao.getDownloadTask();
|
||||
list.forEach(item -> {
|
||||
if(new File(item.getFilePath()).exists()){
|
||||
boolean flag = FileUtil.deleteFile2(item.getFilePath());
|
||||
if(flag){
|
||||
item.setDelete("0");
|
||||
}else{
|
||||
if (!file.delete()) {
|
||||
log.warn("文件删除失败:" + file.getAbsolutePath());
|
||||
item.setDelete("1");
|
||||
}
|
||||
}else{
|
||||
item.setDelete("0");
|
||||
}
|
||||
});
|
||||
if(CollectionUtils.isNotEmpty(list)){
|
||||
downloadTaskDao.updateTaskDownload(list);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
if (!dir.delete()) {
|
||||
log.warn("目录删除失败:" + dir.getAbsolutePath());
|
||||
}
|
||||
// 删除该日期之前的文件夹
|
||||
log.info("--------删除缓存文件定时任务执行完毕------");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.bonus.imgTool.task.dao;
|
||||
|
||||
import com.bonus.imgTool.task.entity.DownloadTaskVo;
|
||||
import com.bonus.imgTool.task.entity.TaskVo;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository(value = "DownloadTaskDao")
|
||||
public interface DownloadTaskDao {
|
||||
|
||||
/**
|
||||
* 查询下载定时任务数据
|
||||
* @return List<DownloadTaskVo>
|
||||
* @author cwchen
|
||||
* @date 2025/4/8 9:59
|
||||
*/
|
||||
List<DownloadTaskVo> getDownloadTask();
|
||||
|
||||
/**
|
||||
* 更新下载定时任务数据
|
||||
* @param list
|
||||
* @return void
|
||||
* @author cwchen
|
||||
* @date 2025/4/8 10:01
|
||||
*/
|
||||
void updateTaskDownload(List<DownloadTaskVo> list);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.bonus.imgTool.task.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @className:DownloadTaskVo
|
||||
* @author:cwchen
|
||||
* @date:2025-04-08-9:51
|
||||
* @version:1.0
|
||||
* @description:文件下载定时任务
|
||||
*/
|
||||
@Data
|
||||
public class DownloadTaskVo {
|
||||
|
||||
private Long id;
|
||||
/**任务id*/
|
||||
private String taskId;
|
||||
/**文件路径*/
|
||||
private String filePath;
|
||||
/**失效时间*/
|
||||
private Date failureTime;
|
||||
/**是否删除*/
|
||||
private String delete;
|
||||
}
|
||||
|
|
@ -845,4 +845,15 @@ public class DateTimeHelper {
|
|||
}
|
||||
return strs;
|
||||
}
|
||||
|
||||
public static String currentTwoHours(){
|
||||
// 获取当前时间
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
System.out.println("当前时间: " + calendar.getTime());
|
||||
// 添加2小时
|
||||
calendar.add(Calendar.HOUR_OF_DAY, 2);
|
||||
Date newDate = calendar.getTime();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return dateFormat.format(newDate);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.imgTool.task.dao.DownloadTaskDao">
|
||||
<!--更新下载定时任务数据-->
|
||||
<update id="updateTaskDownload">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE tb_download_task
|
||||
SET is_delete = #{item.delete}
|
||||
WHERE id = #{item.id}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!--查询下载定时任务数据-->
|
||||
<select id="getDownloadTask" resultType="com.bonus.imgTool.task.entity.DownloadTaskVo">
|
||||
SELECT id,
|
||||
task_id AS taskId,
|
||||
file_path AS filePath
|
||||
FROM tb_download_task
|
||||
WHERE is_delete = '1' AND NOW() > failure_time
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -131,7 +131,7 @@ body {
|
|||
|
||||
.imgData {
|
||||
width: 100%;
|
||||
height: 65%;
|
||||
height: 63%;
|
||||
}
|
||||
|
||||
.img-viewer {
|
||||
|
|
@ -147,7 +147,7 @@ body {
|
|||
|
||||
.imgData2 {
|
||||
width: 100%;
|
||||
height: 8%;
|
||||
height: 10%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.imgData2 > p,.imgData4>p {
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ document.getElementById('downloadBtn').addEventListener('click', function() {
|
|||
downloadLink.onclick = function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = data.downloadUrl;
|
||||
notification.style.display = 'none';
|
||||
window.close();
|
||||
// notification.style.display = 'none';
|
||||
};
|
||||
notification.style.display = 'block';
|
||||
// 2小时后自动隐藏通知
|
||||
setTimeout(() => {
|
||||
notification.style.display = 'none';
|
||||
window.close();
|
||||
}, 1000 * 60 * 60 * 2);
|
||||
// 关闭EventSource连接
|
||||
eventSource.close();
|
||||
|
|
@ -62,6 +62,7 @@ document.getElementById('downloadBtn').addEventListener('click', function() {
|
|||
taskId: taskId,
|
||||
proId: proId,
|
||||
type: type,
|
||||
proName: proName,
|
||||
})
|
||||
}).catch(error => {
|
||||
document.getElementById('statusText').textContent = '启动任务失败';
|
||||
|
|
|
|||
Loading…
Reference in New Issue