大文件分片上传

选择文件



上传进度



<script>
    // 上传文件的起始位置
    var start = 0;
    // 分片大小(5MB)
    var chunkSize = 5 * 1024 * 1024;
    // 上传文件的总大小
    var fileSize = 0;
    // 上传文件的分片总数
    var totalChunks = 0;
    // 当前上传的分片
    var currentChunk = 0;
    // 文件对象
    var file = null;
    // 上传文件的唯一标识符
    var uploadId = null;

    // 选择文件
    var fileInput = document.getElementById('fileInput');
    fileInput.addEventListener('change', function (event) {
        file = event.target.files[0];
        fileSize = file.size;
        totalChunks = Math.ceil(fileSize / chunkSize);
        console.log('文件大小:' + fileSize);
        console.log('分片总数:' + totalChunks);
    });

    function startUpload() {
        // 发送请求,获取上传文件的唯一标识符
        var xhr = new XMLHttpRequest();
        xhr.open('GET', '/getUploadId?fileName=' + file.name + '&fileSize=' + fileSize);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                uploadId = xhr.responseText;
                console.log('上传文件的唯一标识符:' + uploadId);
                // 开始上传文件的第一个分片
                uploadChunk();
            }
        };
        xhr.send();
    }

    function uploadChunk() {
        // 计算当前分片的起始位置和结束位置
        var chunkStart = start + currentChunk * chunkSize;
        var chunkEnd = Math.min(chunkStart + chunkSize, fileSize);
        var chunk = file.slice(chunkStart, chunkEnd);

        // 发送分片上传请求
        var xhr = new XMLHttpRequest();
        xhr.open('POST', '/uploadChunk');
        xhr.setRequestHeader('Content-Type', 'application/octet-stream');
        xhr.setRequestHeader('X-Upload-Id', uploadId);
        xhr.setRequestHeader('X-Chunk-Number', currentChunk + 1);
        xhr.setRequestHeader('X-Total-Chunks', totalChunks);
        xhr.setRequestHeader('X-Chunk-Size', chunkSize);
        xhr.setRequestHeader('X-File-Name', file.name);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                console.log('上传分片成功:' + xhr.responseText);
                // 更新上传进度
                var progress = Math.round((chunkEnd / fileSize) * 100);
                document.getElementById('progressBar').value = progress;
                // 如果还有下一个分片,则继续上传
                if (currentChunk + 1 < totalChunks) {
                    currentChunk++;
                    uploadChunk();
                }
            }
        };
        xhr.send(chunk);
    }
</script>

```java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    // 存储上传文件的目录
    private static final String UPLOAD_DIR = 'uploads/';

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取上传文件的唯一标识符
        String fileName = request.getParameter('fileName');
        long fileSize = Long.parseLong(request.getParameter('fileSize'));
        String uploadId = UUID.randomUUID().toString();

        // 创建分片上传记录文件
        Path path = Paths.get(UPLOAD_DIR + fileName + '.' + uploadId);
        Files.createFile(path);

        // 返回分片上传记录文件的唯一标识符
        response.getWriter().write(uploadId);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取上传文件的唯一标识符、分片编号、分片总数、分片大小、文件名
        String uploadId = request.getHeader('X-Upload-Id');
        int chunkNumber = Integer.parseInt(request.getHeader('X-Chunk-Number'));
        int totalChunks = Integer.parseInt(request.getHeader('X-Total-Chunks'));
        int chunkSize = Integer.parseInt(request.getHeader('X-Chunk-Size'));
        String fileName = request.getHeader('X-File-Name');

        // 获取上传文件的分片
        InputStream inputStream = request.getInputStream();
        byte[] chunk = inputStream.readAllBytes();

        // 将上传文件的分片写入临时文件
        Path path = Paths.get(UPLOAD_DIR + fileName + '.' + uploadId);
        try (OutputStream outputStream = new FileOutputStream(path.toFile(), true)) {
            outputStream.write(chunk);
        }

        // 如果是最后一个分片,则合并分片为完整的上传文件
        if (chunkNumber == totalChunks) {
            // 从临时文件读取上传文件的所有分片
            byte[] fileBytes = Files.readAllBytes(path);
            // 删除临时文件
            Files.delete(path);

            // 创建上传文件的目录(如果不存在)
            Path uploadPath = Paths.get(UPLOAD_DIR);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 写入完整的上传文件
            Path filePath = Paths.get(UPLOAD_DIR + fileName);
            Files.write(filePath, fileBytes);

            // 返回上传成功信息
            response.getWriter().write('上传成功');
        } else {
            // 返回上传分片成功信息
            response.getWriter().write('上传分片成功');
        }
    }
}

说明:

  • 前端代码通过文件选择框选择要上传的文件,然后将文件分成多个分片上传,每个分片大小为5MB。
  • 前端代码通过XMLHttpRequest对象发送GET请求,获取上传文件的唯一标识符。然后通过XMLHttpRequest对象发送POST请求,上传文件的每个分片。
  • 后端代码根据文件名、文件大小和随机生成的UUID创建一个分片上传记录文件,文件名格式为<文件名>.<上传文件的唯一标识符>。每次上传分片时,将分片写入分片上传记录文件。如果是最后一个分片,则将所有分片合并成完整的上传文件,并将上传文件存储到uploads/目录下。
  • 上传文件的唯一标识符、分片编号、分片总数、分片大小和文件名通过HTTP请求头传递。
Java 大文件分片上传前后端代码实现

原文地址: https://www.cveoy.top/t/topic/nPEN 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录