Java实现文件分片上传

文件分片上传
核心思想:前端分片上传,后端合并文件

测试页面

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>文件分片上传</title>
  </head>

  <body>
    <input type="file" id="fileInput" />
    <button onclick="uploadFile()">上传</button>

    <script>
      function uploadFile() {
        const fileInput = document.getElementById('fileInput')
        const file = fileInput.files[0]
        if (!file) {
          alert('请选择文件')
          return
        }

        const chunkSize = 1024 * 1024 // 每个分片 1MB
        const totalChunks = Math.ceil(file.size / chunkSize)
        const identifier = file.name + '_' + file.size

        let currentChunk = 0
        function uploadChunk() {
          const start = currentChunk * chunkSize
          const end = Math.min(start + chunkSize, file.size)
          const chunk = file.slice(start, end)

          const formData = new FormData()
          formData.append('file', chunk)
          formData.append('chunkNumber', currentChunk)
          formData.append('totalChunks', totalChunks)
          formData.append('identifier', identifier)

          const xhr = new XMLHttpRequest()
          xhr.open('POST', 'http://localhost:8080/file/uploadChunk', true)
          xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                const response = JSON.parse(xhr.responseText)
                if (response.success) {
                  currentChunk++
                  if (currentChunk < totalChunks) {
                    uploadChunk()
                  } else {
                    mergeChunks()
                  }
                } else {
                  alert('分片上传失败: ' + response.message)
                }
              } else {
                alert('请求出错: ' + xhr.status)
              }
            }
          }
          xhr.send(formData)
        }

        function mergeChunks() {
          const xhr = new XMLHttpRequest()
          xhr.open('POST', 'http://localhost:8080/file/mergeChunks', true)
          xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                const response = JSON.parse(xhr.responseText)
                if (response.success) {
                  alert('文件上传成功')
                } else {
                  alert('文件合并失败: ' + response.message)
                }
              } else {
                alert('请求出错: ' + xhr.status)
              }
            }
          }
          const mergeData = new FormData()
          mergeData.append('identifier', identifier)
          mergeData.append('totalChunks', totalChunks)
          xhr.send(mergeData)
        }

        uploadChunk()
      }
    </script>
  </body>
</html>

后端代码实现

    private static final String TEMP_DIR = 定义临时目录;

    /**
     * 分片上传文件
     *
     * @param file        文件
     * @param chunkNumber 分片文件下标
     * @param totalChunks 分片总数
     * @param identifier  分片文件标识
     * @return
     */
    public Map<String, Object> uploadChunk(MultipartFile file, int chunkNumber, int totalChunks, String identifier) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 创建临时存储目录
            File tempDir = new File(TEMP_DIR + identifier);
            if (!tempDir.exists()) {
                tempDir.mkdirs();
            }
            // 保存分片文件
            File chunkFile = new File(tempDir, "chunk_" + chunkNumber);
            try (InputStream inputStream = file.getInputStream();
                 FileOutputStream outputStream = new FileOutputStream(chunkFile)) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
            result.put("success", true);
            result.put("message", "分片上传成功");
        } catch (IOException e) {
            result.put("success", false);
            result.put("message", "分片上传失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 合并分片文件
     *
     * @param identifier  分片文件标识
     * @param totalChunks 分片总数
     * @return
     */
    public Map<String, Object> mergeChunks(String identifier, int totalChunks) {
        Map<String, Object> result = new HashMap<>();
        try {
            File tempDir = new File(TEMP_DIR + identifier);
            if (tempDir.exists() && tempDir.isDirectory()) {
                File mergedFile = new File(TEMP_DIR + identifier.split("_")[0]);
                try (FileOutputStream outputStream = new FileOutputStream(mergedFile)) {
                    for (int i = 0; i < totalChunks; i++) {
                        File chunkFile = new File(tempDir, "chunk_" + i);
                        if (chunkFile.exists()) {
                            try (InputStream inputStream = java.nio.file.Files.newInputStream(chunkFile.toPath())) {
                                byte[] buffer = new byte[4096];
                                int bytesRead;
                                while ((bytesRead = inputStream.read(buffer)) != -1) {
                                    outputStream.write(buffer, 0, bytesRead);
                                }
                            }
                            // 删除分片文件
                            chunkFile.delete();
                        }
                    }
                }
                // 删除临时目录
                tempDir.delete();
                result.put("success", true);
                result.put("message", "文件合并成功");
            } else {
                result.put("success", false);
                result.put("message", "临时目录不存在");
            }
        } catch (IOException e) {
            result.put("success", false);
            result.put("message", "文件合并失败: " + e.getMessage());
        }
        return result;
    }
posted @   好事的猫  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
历史上的今天:
2023-02-20 生成系统中的maven依赖信息
点击右上角即可分享
微信分享提示