Java+Layui 实现大文件分片上传前后端代码详解
前端代码
- 引入 Layui 库和 jQuery 库
<!-- 引入 Layui 库 -->
<link rel='stylesheet' href='layui/css/layui.css'>
<script src='layui/layui.all.js'></script>
<!-- 引入 jQuery 库 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
- 构建上传表单
<form class='layui-form' action='' enctype='multipart/form-data'>
<div class='layui-form-item'>
<div class='layui-upload'>
<button type='button' class='layui-btn' id='uploadBtn'>上传文件</button>
<input type='file' name='file' class='layui-upload-file' id='fileInput'>
</div>
</div>
</form>
- 编写上传文件的 JavaScript 代码
layui.use(['layer', 'upload'], function() {
var layer = layui.layer,
upload = layui.upload;
var fileMd5 = ''; // 文件 MD5 值
// 计算文件 MD5 值
function calcFileMd5(file, callback) {
var fileSize = file.size;
var chunkSize = 1024 * 1024; // 1MB
var chunks = Math.ceil(fileSize / chunkSize);
var currentChunk = 0;
var spark = new SparkMD5.ArrayBuffer();
var fileReader = new FileReader();
fileReader.onload = function(e) {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNextChunk();
} else {
var md5 = spark.end();
callback(md5);
}
};
function loadNextChunk() {
var start = currentChunk * chunkSize;
var end = Math.min(start + chunkSize, fileSize);
fileReader.readAsArrayBuffer(file.slice(start, end));
}
loadNextChunk();
}
// 上传文件
upload.render({
elem: '#uploadBtn',
url: '/upload',
auto: false,
bindAction: '#submitBtn',
choose: function(obj) {
var file = obj.pushFile();
calcFileMd5(file, function(md5) {
fileMd5 = md5;
obj.preview(function(index, file, result) {
$('#fileInput').val(file.name);
layer.msg('文件已选择');
});
});
}
});
// 提交表单
$('#submitBtn').on('click', function() {
var formData = new FormData();
formData.append('fileMd5', fileMd5);
formData.append('file', $('#fileInput')[0].files[0]);
$.ajax({
url: '/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(res) {
layer.msg('文件上传成功');
},
error: function(xhr, status, error) {
layer.msg('文件上传失败');
}
});
});
});
后端代码
- 创建上传接口
@RequestMapping("/upload")
public Result upload(HttpServletRequest request) {
String fileMd5 = request.getParameter("fileMd5");
File file = new File("upload/" + fileMd5);
if (!file.exists()) {
file.mkdirs();
}
String fileName = request.getParameter("fileName");
int chunkIndex = Integer.parseInt(request.getParameter("chunkIndex"));
try (InputStream inputStream = request.getInputStream();
OutputStream outputStream = new FileOutputStream(new File(file, fileName + "." + chunkIndex))) {
byte[] buffer = new byte[1024 * 1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
return Result.fail("文件上传失败");
}
return Result.success();
}
- 创建合并文件接口
@RequestMapping("/merge")
public Result merge(HttpServletRequest request) {
String fileMd5 = request.getParameter("fileMd5");
String fileName = request.getParameter("fileName");
int chunkCount = Integer.parseInt(request.getParameter("chunkCount"));
File file = new File("upload/" + fileMd5);
File[] files = file.listFiles((dir, name) -> name.startsWith(fileName + "."));
if (files.length != chunkCount) {
return Result.fail("分片数量不正确");
}
File destFile = new File("upload/" + fileName);
try (OutputStream outputStream = new FileOutputStream(destFile)) {
for (int i = 0; i < chunkCount; i++) {
File chunkFile = new File(file, fileName + "." + i);
try (InputStream inputStream = new FileInputStream(chunkFile)) {
byte[] buffer = new byte[1024 * 1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
return Result.fail("文件合并失败");
}
}
} catch (IOException e) {
e.printStackTrace();
return Result.fail("文件合并失败");
}
return Result.success();
}
原文地址: https://www.cveoy.top/t/topic/nIId 著作权归作者所有。请勿转载和采集!