前端代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>大文件分片上传</title>
</head>

<body>
    <div>
        <h3>选择文件</h3>
        <input type="file" id="fileInput" />
        <br />
        <br />
        <h3>上传进度</h3>
        <progress id="progressBar" value="0" max="100"></progress>
        <br />
        <br />
        <button onclick="startUpload()">开始上传</button>
    </div>

    <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>
</body>

</html>

后端代码:

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前后端代码

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

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