优秀的编程知识分享平台

网站首页 > 技术文章 正文

JAVA实现大文件文件分片上传、断点续传

nanyue 2024-07-29 01:10:00 技术文章 6 ℃


实现大文件的分片上传、断点续传功能需要前后端的配合。以下是一个简单的示例,展示如何使用Java和Spring Boot实现大文件的分片上传、断点续传功能。

  1. 后端 - 使用Spring Boot

首先,确保你的Spring Boot项目已经添加了spring-web的依赖。

pom.xml

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
</dependency>

FileUploadController.java

import org.springframework.web.bind.annotation.*;  
import org.springframework.web.multipart.MultipartFile;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.util.stream.StreamSupport;  
  
@RestController  
public class FileUploadController {  
    private static final String UPLOAD_DIR = "uploads/";  
    private static final int CHUNK_SIZE = 1024 * 1024; // 1MB  
  
    @PostMapping("/upload")  
    public String uploadFile(@RequestParam("file") MultipartFile file,  
                              @RequestParam("chunk") int chunk,  
                              @RequestParam("chunks") int chunks) throws Exception {  
        Path targetFile = Paths.get(UPLOAD_DIR + file.getOriginalFilename());  
        byte[] buffer = new byte[CHUNK_SIZE];  
        long startByte = chunk * CHUNK_SIZE;  
        try (InputStream is = new ByteArrayInputStream(file.getBytes());  
             RandomAccessFile raf = new RandomAccessFile(targetFile.toFile(), "rw")) {  
            raf.seek(startByte);  
            StreamUtils.copy(is, raf, buffer);  
        }  
        return "Chunk " + chunk + " uploaded successfully.";  
    }  
  
    @GetMapping("/merge")  
    public String mergeFile(@RequestParam("fileName") String fileName, @RequestParam("chunkCount") int chunkCount) throws Exception {  
        Path targetFile = Paths.get(UPLOAD_DIR + fileName);  
        try (RandomAccessFile raf = new RandomAccessFile(targetFile.toFile(), "rw")) {  
            for (int i = 0; i < chunkCount; i++) {  
                byte[] buffer = new byte[CHUNK_SIZE];  
                raf.seek(i * CHUNK_SIZE);  
                raf.write(buffer);  
            }  
        }  
        return "File merged successfully.";  
    }  
}
  1. 前端 - 使用HTML5和JavaScript

在前端,你可以使用HTML5的<input type="file">来选择一个文件,并使用JavaScript将其分片并上传到服务器。这里只是一个简单的示例,真实的应用中你可能需要添加更多的功能,如进度条、错误处理等。

index.html

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>大文件分片上传示例</title>  
</head>  
<body>  
    <input type="file" id="fileInput">  
    <button onclick="uploadFile()">Upload</button>  
    <script src="app.js"></script>  
</body>  
</html>

app.js

户体

function uploadFile() {  
    let fileInput = document.getElementById('fileInput');  
    let file = fileInput.files[0];  
    let chunkSize = 1024 * 1024; // 1MB  
    let chunks = Math.ceil(file.size / chunkSize);  
    let currentChunk = 0;  
    let formData = new FormData();  
    formData.append('fileName', file.name);  
    formData.append('chunkCount', chunks);  
    fetch('/merge', { method: 'POST', body: formData }) // 先通知后端文件总片数,以便后端准备合并文件  
        .then(() => {  
            function sendNext() {  
                let blob = file.slice(currentChunk * chunkSize, (currentChunk + 1) * chunkSize);  
                formData = new FormData();  
                formData.append('file', blob);  
                formData.append('chunk', currentChunk);  
                formData.append('chunks', chunks);  
                fetch('/upload', { method: 'POST', body: formData }) // 上传当前分片至服务器,成功后发送下一分片。若失败,可从断点续传。具体逻辑根据需求自行实现。然后递归调用自身,实现分片上传功能。当currentChunk等于chunks时,说明所有分片已经上传完毕。此时可以通知后端进行文件合并操作。
            }).then(()=>{
              currentChunk++;
              if(currentChunk<chunks){sendNext()}
            })catch((error)=>{console.log(error)});

uploadFile()函数是整个文件上传的入口函数,首先获取到用户选择的文件,并计算出文件的总片数和每片的大小。然后调用sendNext()函数开始上传文件的第一个分片。sendNext()函数中,使用fetch API向后端发送POST请求,上传当前分片,并携带当前分片的索引和总片数信息。

后端在接收到分片后,将分片写入到对应的文件中,并返回成功响应。前端在接收到成功响应后,递归调用sendNext()函数,上传下一个分片,直到所有分片上传完毕。此时可以通知后端进行文件合并操作。后端在接收到合并请求后,将所有分片按照顺序合并成一个完整的文件,并返回成功响应。前端在接收到成功响应后,提示用户文件上传成功。注意:上述代码只是一个简单的示例,真实的应用中你需要处理更多的边界情况和错误情况,如网络中断、文件不存在等。同时,你还需要考虑如何保证上传的文件的安全性和隐私性。

上述代码提供了一个大文件分片上传和断点续传的基本框架。但请注意,实际生产环境中需要考虑更多的细节和异常情况。此外,为了提高用户体验和上传效率,你可能还需要添加进度条、并行上传、重试机制等功能。

最近发表
标签列表