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;
}
本文来自博客园,作者:好事的猫,转载请注明原文链接:https://www.cnblogs.com/BeiJiuGuRen/p/18726396
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
2023-02-20 生成系统中的maven依赖信息