主要思路
每次上传文件时,根据文件的文件名判断上传文件目录是否有对应文件。
如果有文件,返回当前文件的文件长度,前端可使用进度条展示文件的上传进度。
SpringMVC
@PostMapping(value = "/fileUpload")
public Long fileUpload(MultipartHttpServletRequest request) throws IOException {
MultipartFile file = request.getFile("file");
String fileName = request.getParameter("fileName");
String position = request.getParameter("position");
if (file != null) {
if (!StringUtils.hasLength(position)) {
save(fileName, file.getInputStream());
} else {
File targetFile = new File("E:/", fileName);
keepGoing(file.getInputStream(), targetFile, Integer.parseInt(position));
}
}
return getFileSize(fileName);
}
根据文件名写入上传文件夹
private static void save(String fileName, InputStream inputStream) {
// 目标文件
File targetFile = new File("E:/", fileName);
// 输入输出流
FileInputStream fis = null;
FileOutputStream fos = null;
// 数据缓冲区
byte[] buf = new byte[10];
try {
fis = (FileInputStream) inputStream;
fos = new FileOutputStream(targetFile);
// 数据读写
while (fis.read(buf) != -1) {
fos.write(buf);
break;
}
} catch (FileNotFoundException e) {
System.out.println("指定文件不存在");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭输入输出流
if (fis != null)
fis.close();
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
RandomAccessFile
使用RandomAccessFile,对file文件输入流从指定位置开始写数据。
private static void keepGoing(InputStream inputStream, File target, int position) {
RandomAccessFile writeFile = null;
try {
writeFile = new RandomAccessFile(target, "rw");
writeFile.seek(position);
// 数据缓冲区
byte[] buf = new byte[1024];
// 数据读写
while (inputStream.read(buf) != -1) {
writeFile.write(buf);
break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writeFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
获取文件长度
@GetMapping(value = "/getFilePosition/{fileName}")
public Long getFilePosition(@PathVariable String fileName) {
File targetFile = new File("E:/", fileName);
if (!targetFile.exists()) {
return 0L;
}
return targetFile.length();
}
private static Long getFileSize(String fileName) {
File targetFile = new File("E:/", fileName);
return targetFile.length();
}
前端代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<input type="file" multiple="multiple" name="file" id="file" onchange="init()">
<br>
<progress id="progress" max="100" value="0"></progress>
<br>
<button id="upload">上传</button>
</body>
<script type="application/javascript">
var position = 0;
$("#upload").click(function(){
let file = $('#file')[0].files[0];
const formData = new FormData();
formData.append('file', file.slice(position, file.size));
formData.append('fileName', getFileName())
formData.append('position', position)
$.ajax({
url: '/fileUpload',
type: 'POST',
cache: false, //上传文件不需要缓存
data: formData,
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
success: function (res) {
document.getElementById('progress').max = file.size;
document.getElementById('progress').value = res;
},
error: function (err) {
console.log(err)
}
})
});
function check(){
// 校验是否上传过文件
// 返回上次上传位置
$.ajaxSettings.async = false;
$.get('/getFilePosition/' + getFileName(), function (data){
position = data;
document.getElementById('progress').value = data;
})
$.ajaxSettings.async = true;
}
function getFileName(){
let originalFileName = $('#file').val();
return originalFileName.substring(originalFileName.lastIndexOf('\\') + 1);
}
function init(){
let file = $('#file')[0].files[0];
document.getElementById('progress').max = file.size;
check();
}
</script>
</html>