Xiajijian
2026-02-05 5ea2094378f25a3f98d8f370dafaf9367c05c2e5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.ard.inspection.service.impl;
 
import com.ard.inspection.service.IBigFileUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @author xia
 */
@Service
@Slf4j
public class BigFileUploadServiceImpl implements IBigFileUploadService {
 
    @Override
    public Map<String, Object> checkChunk(String fileMd5,String chunkPath) {
        Map<String, Object> result = new HashMap<>();
        try {
            File chunkFolder = new File(chunkPath + File.separator + fileMd5);
            if (!chunkFolder.exists()) {
                result.put("exception", "分片不存在!!!");
                return result;
            }
 
            File[] chunks = chunkFolder.listFiles();
            if (chunks == null || chunks.length == 0) {
                result.put("exception", "无分片!!!");
                return result;
            }
 
            List<Integer> uploadedChunks = Arrays.stream(chunks)
                    .map(file -> Integer.parseInt(file.getName().split("\\.")[0]))
                    .collect(Collectors.toList());
            result.put("message", uploadedChunks);
            return result;
        } catch (Exception e) {
            log.error("检查分片失败", e);
            result.put("exception", "检查分片失败!!!");
            return result;
        }
    }
 
    @Override
    public Map<String, Object> uploadChunk(MultipartFile file,
                              Integer chunkNumber,
                              String fileMd5,
                              String chunkPath) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 验证参数
            if (file.isEmpty()) {
                result.put("exception", "文件不能为空!!!");
                return result;
            }
 
            // 创建分片目录
            String chunkDirPath = chunkPath + File.separator + fileMd5;
            File chunkDir = new File(chunkDirPath);
            if (!chunkDir.exists()) {
                chunkDir.mkdirs();
            }
 
            // 保存分片
            String chunkFileName = chunkNumber + ".part";
            File chunkFile = new File(chunkDir, chunkFileName);
            file.transferTo(chunkFile);
 
            result.put("message", "分片上传成功!!!");
            return result;
        } catch (IOException e) {
            log.error("分片上传失败", e);
            result.put("exception", "分片上传失败!!!");
            return result;
        }
    }
 
    @Override
    public Map<String, Object> mergeChunks(String md5,String fileName,String uploadPath) {
        Map<String, Object> result = new HashMap<>();
        // 临时目录
        String chunkDir = uploadPath + File.separator + md5;
        File dir = new File(chunkDir);
        if (!dir.exists()) {
            result.put("exception", "切片目录不存在");
            return result;
        }
        // 获取所有切片文件
        File[] chunks = dir.listFiles();
        if (chunks == null || chunks.length == 0) {
            result.put("exception", "没有切片文件");
            return result;
        }
        // 按照切片索引排序
        Arrays.sort(chunks, (a, b) -> {
            int aIndex = Integer.parseInt(a.getName().split("\\.")[0]);
            int bIndex = Integer.parseInt(b.getName().split("\\.")[0]);
            return aIndex - bIndex;
        });
 
        // 合并后的文件,这里使用原始文件名,为了避免重名,可以加上时间戳或使用UUID
        // 这里根据业务需求,可以保存到数据库,记录文件路径等信息
        String ext = fileName.substring(fileName.lastIndexOf("."));
        String newFileName = UUID.randomUUID().toString().replace("-", "") + ext; // 生成新文件名
        File mergeFile = new File(uploadPath, newFileName);
 
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(mergeFile, "rw")) {
            byte[] buffer = new byte[1024 * 1024]; // 1MB缓冲区
            for (File chunk : chunks) {
                try (RandomAccessFile chunkFile = new RandomAccessFile(chunk, "r")) {
                    int len;
                    while ((len = chunkFile.read(buffer)) != -1) {
                        randomAccessFile.write(buffer, 0, len);
                    }
                }
                // 删除切片文件
                chunk.delete();
            }
            // 删除临时目录
            dir.delete();
        } catch (IOException e) {
            log.error("合并文件失败", e);
            result.put("exception", "合并文件失败");
            return result;
        }
 
        // 这里可以保存文件信息到数据库,例如文件路径、文件名、md5等
        // fileService.saveFileInfo(...);
 
        result.put("message", "文件合并成功");
        return result;
    }
 
}