当前位置: 首页 > news >正文

10、《文件上传与下载:MultipartFile与断点续传设计》

文件上传与下载:MultipartFile与断点续传设计

一、基础文件上传与MultipartFile解析

1.1 Spring MVC文件上传基础

@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {if (!file.isEmpty()) {try {byte[] bytes = file.getBytes();Path path = Paths.get("uploads/" + file.getOriginalFilename());Files.write(path, bytes);return "redirect:/success";} catch (IOException e) {e.printStackTrace();}}return "redirect:/error";
}

1.2 MultipartFile核心方法解析

public interface MultipartFile {String getName();         // 表单字段名称String getOriginalFilename(); // 原始文件名String getContentType();  // MIME类型boolean isEmpty();        // 是否空文件long getSize();           // 文件字节大小byte[] getBytes() throws IOException;InputStream getInputStream() throws IOException;void transferTo(File dest) throws IOException;
}

二、大文件分片上传设计

2.1 分片上传原理

2.2 前端分片处理示例(JavaScript)

const CHUNK_SIZE = 5 * 1024 * 1024; // 5MBasync function uploadFile(file) {const fileHash = await calculateMD5(file);const chunks = Math.ceil(file.size / CHUNK_SIZE);for (let i = 0; i < chunks; i++) {const chunk = file.slice(i * CHUNK_SIZE, (i+1)*CHUNK_SIZE);const formData = new FormData();formData.append('chunk', chunk);formData.append('chunkNumber', i);formData.append('totalChunks', chunks);formData.append('fileHash', fileHash);await axios.post('/api/upload-chunk', formData);}
}

2.3 后端分片接收处理

@PostMapping("/upload-chunk")
public ResponseEntity<?> uploadChunk(@RequestParam("chunk") MultipartFile chunk,@RequestParam("chunkNumber") int chunkNumber,@RequestParam("totalChunks") int totalChunks,@RequestParam("fileHash") String fileHash) {String tempDir = "temp/" + fileHash + "/";FileUtils.forceMkdir(new File(tempDir));try {chunk.transferTo(new File(tempDir + chunkNumber));return ResponseEntity.ok().build();} catch (IOException e) {return ResponseEntity.status(500).build();}
}

三、断点续传关键技术

3.1 断点续传实现要素

  • 唯一文件标识(MD5/SHA1)
  • 分片索引记录
  • 已上传分片校验
  • 分片合并策略

3.2 断点信息存储(Redis示例)

@Service
public class UploadProgressService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String UPLOAD_PROGRESS_KEY = "upload:progress:";public void saveProgress(String fileHash, Set<Integer> chunks) {redisTemplate.opsForSet().add(UPLOAD_PROGRESS_KEY + fileHash, chunks.toArray(new Integer[0]));}public Set<Integer> getProgress(String fileHash) {return redisTemplate.opsForSet().members(UPLOAD_PROGRESS_KEY + fileHash).stream().map(o -> (Integer)o).collect(Collectors.toSet());}
}

四、OSS云存储集成方案

4.2 阿里云OSS分片上传示例

// OSS配置类
@Configuration
public class OssConfig {@Value("${oss.endpoint}")private String endpoint;@Value("${oss.accessKey}")private String accessKey;@Value("${oss.secretKey}")private String secretKey;@Beanpublic OSS ossClient() {return new OSSClientBuilder().build(endpoint, accessKey, secretKey);}
}// 分片上传服务
@Service
@RequiredArgsConstructor
public class OssUploadService {private final OSS ossClient;public String multipartUpload(String bucketName, String objectName, File file) {InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);String uploadId = result.getUploadId();// 分片上传逻辑List<PartETag> partETags = new ArrayList<>();long contentLength = file.length();int partSize = 5 * 1024 * 1024; // 5MBtry (FileInputStream fis = new FileInputStream(file)) {for(int i = 1; fis.available() > 0; i++) {UploadPartRequest uploadPartRequest = new UploadPartRequest();uploadPartRequest.setBucketName(bucketName);uploadPartRequest.setKey(objectName);uploadPartRequest.setUploadId(uploadId);uploadPartRequest.setInputStream(fis);uploadPartRequest.setPartSize(partSize);uploadPartRequest.setPartNumber(i);UploadPartResult uploadResult = ossClient.uploadPart(uploadPartRequest);partETags.add(uploadResult.getPartETag());}CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);ossClient.completeMultipartUpload(completeRequest);return objectName;}}
}

五、完整项目目录结构

file-upload-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── config/
│   │   │           │   └── OssConfig.java
│   │   │           ├── controller/
│   │   │           │   └── FileController.java
│   │   │           ├── service/
│   │   │           │   ├── UploadService.java
│   │   │           │   └── impl/
│   │   │           │       ├── LocalUploadServiceImpl.java
│   │   │           │       └── OssUploadServiceImpl.java
│   │   │           ├── util/
│   │   │           │   └── FileUtils.java
│   │   │           └── FileUploadDemoApplication.java
│   │   └── resources/
│   │       ├── application.yml
│   │       └── static/
├── pom.xml
└── README.md

六、性能优化建议

  1. 动态分片大小调整(网络质量检测)
  2. 并行分片上传(前端Promise.all)
  3. 客户端计算文件指纹(Web Worker)
  4. 分片完整性校验(SHA-256)
  5. 自动重试机制(指数退避策略)

总结

本文从基础文件上传实现出发,深入剖析了分片上传与断点续传的核心技术,并结合云存储服务给出了企业级解决方案。示例代码可直接集成到Spring Boot项目中,建议根据实际业务需求调整分片策略和存储方案。

http://www.lryc.cn/news/536020.html

相关文章:

  • DeepSeek 本地部署(电脑安装)
  • DeepSeek、Kimi、文心一言、通义千问:AI 大语言模型的对比分析
  • Docker compose 以及镜像使用
  • HCIA项目实践--RIP相关原理知识面试问题总结回答
  • 使用Python进行云计算:AWS、Azure、和Google Cloud的比较
  • c++ 实现矩阵乘法
  • 无线4G多联机分户计费集中控制系统
  • 文字转语音(一)各种实现说明
  • 大语言模型多代理协作(MACNET)
  • 【笛卡尔树】
  • Java堆外内存的高效利用与性能优化
  • 【Unity3D优化】使用ASTC压缩格式优化内存
  • iptables网络安全服务详细使用
  • MiC建筑引领未来:中建海龙的探索与实践
  • 清华精品资料:DeepSeek从入门到精通、DeepSeek赋能职场
  • Nginx进阶篇 - nginx多进程架构详解
  • SpringBoot初始化8个常用方法
  • boolen盲注和时间盲注
  • CTF-web:java-h2 堆叠注入rec -- N1ctf Junior EasyDB
  • TUSB422 MCU 软件用户指南
  • BUU37 [DASCTF X GFCTF 2024|四月开启第一局]web1234100
  • 常见的排序算法:插入排序、选择排序、冒泡排序、快速排序
  • vue学习9
  • TDengine 性能测试工具 taosBenchmark
  • 【xdoj离散数学上机】T283
  • Javaweb中,使用Servlet编写简单的接口
  • GESP5级语法知识(十):初级数论(三)
  • “PEP 8: W292 no newline at end of file“报错 IntelliJ IDEA自动添加空行问题
  • ComfyUI工作流 FluxRedux基础换装
  • 【机器学习】常见采样方法详解