<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
import org.apache.commons.codec.digest.DigestUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class FileProcessor {
/**
* 演示使用
*/
public static void main(String[] args) {
String testFile = "E:/jt/save/寂寞的季节.mp4";
try {
// 每片大小10M
long chunkSize = 10L * 1024 * 1024;
// 1.计算原文件MD5(模拟前端)
InputStream inputStream = Files.newInputStream(Paths.get(testFile));
String originalMD5 = DigestUtils.md5Hex(inputStream);
System.out.println("Original MD5: " + originalMD5);
// 2.分片处理(10MB分片)(模拟前端)
List<String> chunks = splitFile(testFile, chunkSize);
System.out.println("Generated chunks: " + chunks.size());
// 3.分片合并(模拟后端分片上传)
for (int i = 0; i < chunks.size(); i++) {
byte[] bytes = Files.readAllBytes(Paths.get(chunks.get(i)));
saveChunk(bytes, i, chunkSize, "E:\\jt\\save\\"+originalMD5+".mp4");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件分片(自动处理剩余字节)
* @param sourceFile 源文件路径
* @param chunkSizeBytes 分片大小(b)
* @return 分片文件路径列表
*/
public static List<String> splitFile(String sourceFile, long chunkSizeBytes) throws IOException {
List<String> chunks = new ArrayList<>();
try (RandomAccessFile raf = new RandomAccessFile(sourceFile, "r")) {
long fileSize = raf.length();
int chunkIndex = 0;
long bytesProcessed = 0;
while (bytesProcessed < fileSize) {
long remaining = fileSize - bytesProcessed;
int currentChunkSize = (int) Math.min(chunkSizeBytes, remaining);
// 生成分片文件路径
String chunkPath = sourceFile + ".part" + chunkIndex;
try (RandomAccessFile chunkRaf = new RandomAccessFile(chunkPath, "rw")) {
copyBytes(raf, chunkRaf, bytesProcessed, currentChunkSize);
}
chunks.add(chunkPath);
bytesProcessed += currentChunkSize;
chunkIndex++;
}
}
return chunks;
}
/**
* 安全字节拷贝(带边界检查)
*/
private static void copyBytes(RandomAccessFile src, RandomAccessFile dest,
long startPos, int chunkSize) throws IOException {
src.seek(startPos);
byte[] buffer = new byte[4096];
int totalRead = 0;
while (totalRead < chunkSize) {
int remaining = chunkSize - totalRead;
int bytesToRead = Math.min(buffer.length, remaining);
int bytesRead = src.read(buffer, 0, bytesToRead);
if (bytesRead == -1) {
break;
}
dest.write(buffer, 0, bytesRead);
totalRead += bytesRead;
}
}
public static void saveChunk(byte[] bytes, Integer index, Long chunkSize, String resultFileName) {
try (RandomAccessFile randomAccessFile = new RandomAccessFile(resultFileName, "rw")) {
// 偏移量
long offset = chunkSize * index;
// 定位到该分片的偏移量
randomAccessFile.seek(offset);
// 写入
randomAccessFile.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}