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

断点续传使用场景,完整前后端实现示例,包括上传,下载,验证

断点续传在多个场景中非常有用,包括但不限于大文件上传、跨国或跨区域文件传输、移动设备文件传输、备份和同步以及软件更新等。接下来,我将为你提供一个基于Java的后端实现示例,结合前端逻辑来完成整个断点续传的功能,包括上传、下载和验证。

后端实现(使用Spring Boot)

添加依赖

首先,在pom.xml中添加必要的依赖:

<dependencies><!-- Spring Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Apache Commons IO for file handling --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><!-- Jackson for JSON processing --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
</dependencies>
控制器代码
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;@RestController
@RequestMapping("/api")
public class FileController {private static final String UPLOAD_DIR = "uploads/";@PostMapping("/upload")public ResponseEntity<?> uploadChunk(@RequestParam("file") MultipartFile file,@RequestParam("fileName") String fileName,@RequestParam("chunkIndex") int chunkIndex,@RequestParam("totalChunks") int totalChunks) throws IOException {// 创建目录String dirPath = UPLOAD_DIR + fileName;new File(dirPath).mkdirs();// 保存分片File chunkFile = new File(dirPath, chunkIndex + ".part");try (OutputStream os = new FileOutputStream(chunkFile)) {os.write(file.getBytes());}// 记录已上传的分片Set<Integer> uploadedChunks = loadUploadedChunks(fileName);uploadedChunks.add(chunkIndex);saveUploadedChunks(fileName, uploadedChunks);if (uploadedChunks.size() == totalChunks) {mergeChunks(fileName, totalChunks);}return ResponseEntity.ok().build();}@GetMapping("/download")public ResponseEntity<byte[]> download(@RequestParam("fileName") String fileName) throws IOException {String filePath = UPLOAD_DIR + fileName + "/" + fileName;byte[] bytes = Files.readAllBytes(Paths.get(filePath));return ResponseEntity.ok().header("Content-Disposition", "attachment; filename=" + fileName).body(bytes);}@GetMapping("/check")public ResponseEntity<Map<String, Object>> check(@RequestParam("fileName") String fileName) {Set<Integer> uploadedChunks = loadUploadedChunks(fileName);Map<String, Object> response = new HashMap<>();response.put("uploadedChunks", uploadedChunks);return ResponseEntity.ok(response);}private Set<Integer> loadUploadedChunks(String fileName) {String filePath = UPLOAD_DIR + fileName + "/uploadedChunks.json";File file = new File(filePath);Set<Integer> chunks = new HashSet<>();if (file.exists()) {try {chunks = new HashSet<>(Arrays.asList(FileUtils.readFileToString(file, "UTF-8").split(","))).stream().map(Integer::parseInt).collect(Collectors.toSet());} catch (IOException e) {e.printStackTrace();}}return chunks;}private void saveUploadedChunks(String fileName, Set<Integer> uploadedChunks) {String filePath = UPLOAD_DIR + fileName + "/uploadedChunks.json";try {FileUtils.writeStringToFile(new File(filePath), String.join(",", uploadedChunks.stream().map(String::valueOf).toList()), "UTF-8");} catch (IOException e) {e.printStackTrace();}}private void mergeChunks(String fileName, int totalChunks) throws IOException {String dirPath = UPLOAD_DIR + fileName;String mergedFilePath = UPLOAD_DIR + fileName + "/" + fileName;try (OutputStream os = new FileOutputStream(mergedFilePath)) {for (int i = 0; i < totalChunks; i++) {File chunkFile = new File(dirPath, i + ".part");byte[] bytes = Files.readAllBytes(chunkFile.toPath());os.write(bytes);Files.delete(chunkFile.toPath());}}}
}

前端实现(使用Vue.js)

安装依赖

确保你已经安装了axios用于HTTP请求处理:

npm install axios
上传组件
<template><div><input type="file" @change="selectFile"><button @click="upload">上传</button></div>
</template><script>
import axios from 'axios';export default {data() {return {file: null,chunkSize: 5 * 1024 * 1024, // 5MBuploadedChunks: []};},methods: {selectFile(e) {this.file = e.target.files[0];this.uploadedChunks = [];},async upload() {const fileName = this.file.name;const totalChunks = Math.ceil(this.file.size / this.chunkSize);// 获取已上传的分片信息const { data } = await axios.get('/api/check', { params: { fileName } });this.uploadedChunks = data.uploadedChunks;for (let i = 0; i < totalChunks; i++) {if (this.uploadedChunks.includes(i)) continue;const start = i * this.chunkSize;const end = Math.min(start + this.chunkSize, this.file.size);const chunk = this.file.slice(start, end);const formData = new FormData();formData.append('file', new Blob([chunk]));formData.append('fileName', fileName);formData.append('chunkIndex', i);formData.append('totalChunks', totalChunks);await axios.post('/api/upload', formData);this.uploadedChunks.push(i);}alert('文件上传成功');}}
};
</script>
下载组件
<template><div><input type="text" v-model="fileName"><button @click="download">下载</button></div>
</template><script>
import axios from 'axios';export default {data() {return {fileName: ''};},methods: {async download() {const response = await axios.get('/api/download', { params: { fileName: this.fileName }, responseType: 'blob' });const url = window.URL.createObjectURL(new Blob([response.data]));const link = document.createElement('a');link.href = url;link.setAttribute('download', this.fileName);document.body.appendChild(link);link.click();}}
};
</script>
验证组件
<template><div><input type="text" v-model="fileName"><button @click="check">验证</button><p>已上传分片:{{ uploadedChunks }}</p></div>
</template><script>
import axios from 'axios';export default {data() {return {fileName: '',uploadedChunks: []};},methods: {async check() {const { data } = await axios.get('/api/check', { params: { fileName: this.fileName } });this.uploadedChunks = data.uploadedChunks;}}
};
</script>

这个示例展示了如何使用Spring Boot作为后端,并结合Vue.js前端来实现断点续传功能。你可以根据自己的需求进行调整和优化,例如增加错误处理、进度条显示等功能。

http://www.xdnf.cn/news/462205.html

相关文章:

  • 麒麟系统ARM64架构部署mysql、jdk和java项目
  • 牛客网刷题:NC208813求逆序数
  • 【PX4飞控】在 Matlab Simulink 中使用 Mavlink 协议与 PX4 飞行器进行交互
  • python处理异常,JSON
  • 数据结构—排序(斐波那契数列,冒泡,选择,插入,快速,归并,图,广度优先算法)
  • NSSCTF [GFCTF 2021]where_is_shell
  • 【MySQL】多表连接查询
  • postgresql主从+repmgr+keepalive安装
  • Google DeepMind 推出AlphaEvolve
  • Trivy:让你时刻掌控的开源安全扫描器
  • 产线视觉检测设备技术方案:基于EFISH-SCB-RK3588/SAIL-RK3588的国产化替代赛扬N100/N150全场景技术解析
  • SQL:MySQL函数:条件函数(Conditional Functions)
  • OpenCV人脸识别EigenFace算法、案例解析
  • [学习]RTKLib详解:tle.c(系列终章)
  • 一般的析因设计
  • 探索Turn.js:打造惊艳的3D翻页效果
  • 2025年,如何制作并部署一个完整的个人博客网站
  • 让三个线程(t1、t2、t3)按顺序依次打印 A、B、C
  • 网站漏洞存在哪些危害,该如何做好预防?
  • Java中的深拷贝与浅拷贝
  • Blender 入门教程(三):骨骼绑定
  • 三目云台20倍变焦智能监控技术
  • 基于Arduino的迷你掌上游戏机
  • TCP(传输控制协议)建立连接的过程
  • 黑马k8s(七)
  • 用户安全架构设计
  • Unity碰撞检测:射线与胶囊体投射/Layer(层)、LayerMask(遮罩层)
  • 分布式AI推理的成功之道
  • How to configure Linux mint desktop
  • SpringBoot核心优势与适用场景分析