Spring Boot @Scheduled任务实现S3文件上传按需暂停/恢复方案咨询
基于Spring Boot后端实现S3上传任务的暂停/恢复/追踪方案
核心思路:改造@Scheduled调度器为可控制任务
@Scheduled默认由Spring任务调度器管理独立线程,但通过外部状态控制+任务拆分,无需完全重写现有上传逻辑就能实现暂停/恢复功能。
1. 新增任务状态管理Bean
创建全局状态管理类,存储任务状态与上传进度,保证线程安全:
@Component public class S3UploadTaskStatus { private volatile boolean paused = false; private AtomicLong uploadedBytes = new AtomicLong(0); private AtomicLong totalBytes = new AtomicLong(0); public void pause() { this.paused = true; } public void resume() { this.paused = false; } public void updateUploadedBytes(long bytes) { uploadedBytes.addAndGet(bytes); } public void setTotalBytes(long bytes) { totalBytes.set(bytes); } public boolean isPaused() { return paused; } public double getProgress() { return totalBytes.get() == 0 ? 0 : (double) uploadedBytes.get() / totalBytes.get(); } }
2. 改造原有@Scheduled任务
在上传逻辑中加入状态检查,拆分任务单元(单文件/分片),实现即时暂停与进度追踪:
@Component public class S3UploadScheduler { @Autowired private AmazonS3 amazonS3; @Autowired private S3UploadTaskStatus taskStatus; @Scheduled(fixedRate = 5000) // 保留原调度频率 public void uploadToS3() { if (taskStatus.isPaused()) { return; } List<File> filesToUpload = getFilesToUpload(); taskStatus.setTotalBytes(calculateTotalBytes(filesToUpload)); for (File file : filesToUpload) { if (taskStatus.isPaused()) { break; } // 大文件可替换为AWS分片上传逻辑 PutObjectRequest request = new PutObjectRequest("your-bucket", file.getName(), file); request.setGeneralProgressListener(progressEvent -> { taskStatus.updateUploadedBytes(progressEvent.getBytesTransferred()); }); amazonS3.putObject(request); } } }
3. 暴露后端API供UI调用
创建Controller提供暂停/恢复/进度查询接口:
@RestController @RequestMapping("/upload/task") public class UploadTaskController { @Autowired private S3UploadTaskStatus taskStatus; @PostMapping("/pause") public ResponseEntity<Void> pauseTask() { taskStatus.pause(); return ResponseEntity.ok().build(); } @PostMapping("/resume") public ResponseEntity<Void> resumeTask() { taskStatus.resume(); return ResponseEntity.ok().build(); } @GetMapping("/progress") public ResponseEntity<Map<String, Object>> getProgress() { Map<String, Object> progress = new HashMap<>(); progress.put("status", taskStatus.isPaused() ? "PAUSED" : "RUNNING"); progress.put("progress", taskStatus.getProgress()); return ResponseEntity.ok(progress); } }
4. UI端简单实现
通过定时请求进度接口展示状态,提供操作按钮:
<div> <h3>S3上传任务状态</h3> <div>当前进度:<span id="progress">0%</span></div> <div>当前状态:<span id="status">RUNNING</span></div> <button id="pauseBtn">暂停</button> <button id="resumeBtn">恢复</button> </div> <script> setInterval(() => { fetch('/upload/task/progress') .then(res => res.json()) .then(data => { document.getElementById('progress').textContent = (data.progress * 100).toFixed(2) + '%'; document.getElementById('status').textContent = data.status; }); }, 1000); document.getElementById('pauseBtn').addEventListener('click', () => { fetch('/upload/task/pause', { method: 'POST' }); }); document.getElementById('resumeBtn').addEventListener('click', () => { fetch('/upload/task/resume', { method: 'POST' }); }); </script>
关键注意事项
- 大文件上传建议使用AWS SDK的分片上传(Multipart Upload),状态类中可记录已完成分片ID,恢复时直接续传,避免重复上传。
- 若调度任务为一次性触发,可将@Scheduled改为
@Async异步任务,状态控制逻辑保持一致。
内容的提问来源于stack exchange,提问作者7msseven
相关产品推荐
相关产品推荐

