有的时候我们想要操作的文件很大,比如:我们想要上传一个大文件,但是收到上传文件大小的限制,无法上传,这是我们可以将一个大的文件分割成若干个小文件进行操作,然后再把小文件还原成源文件。
<div id="">
<form class="form-horizontal" enctype="multipart/form-data" id="formImport" >
<input type="hidden" id="taskid" value="${taskid}">
<input type="hidden" id="tpid" value="${tpid}">
<!-- 单个文件上传 -->
<input type="file" id="xlsFile" name="excelFile" />
<input type="button" name="submit" value="submit"
onclick="submitForm(0,1)">
</form>
</div>
<!-- submitForm触发上传由 0 字节开始上传,命名由第 1 部分开始-->
对应的js
function submitForm(begin,part){
var file = $('#xlsFile')[0].files[0];
//console.log(file);
const LENGTH = 1024 * 1024 * 10;//每次上传的大小
var totalSize = file.size; //文件总大小
var start = begin; //每次上传的开始字节
var end = start + LENGTH; //每次上传的结尾字节
var blob = null; //二进制对象
//uploadUrl: location.pathname + '/batch?taskid='+taskid+'&tpid='+tpid,
blob = file.slice(start,end); //截取每次需要上传字节数
formData = new FormData(); //每一次需重新创建
formData.append('file',blob); //添加数据到表单对象中
formData.append('fileName',file.name);//上传文件的名字
formData.append('part',part); //上传第几部分
$.ajax({
url:location.pathname + '/slice?taskid='+taskid+'&tpid='+tpid,
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function(result){
if(result.code==200){
start = end; // 累计上传字节数
end = start + LENGTH; // 由上次完成的部分字节开始,添加下次上传的字节数
part++; // 上传文件部分累计
if(start>=totalSize){ //如果上传字节数大于或等于总字节数,结束上传
alert('上传完成!');
//告诉后台上传完成后合并文件 //返回上传文件的存放路径
$.post(location.pathname + '/mergetFile',{fileName:file.name,path:result.path},function(result){
if(result.code==200){
alert('合并完成!');
}
});
}else{
submitForm(start,part); // 上传字节不等与或大于总字节数,继续上传
}
}
}).fail(function() {
});
}
后台使用了spring mvc
/**
* 切割上传
* */
@PostMapping("/upload2/slice")
@ResponseBody
public Map<String,Object> ObjectsliceUpload(@RequestParam("file") MultipartFile file,String fileName,Integer part,long taskid,long tpid) throws Exception
{
Map<String, Object> map = new HashMap<String, Object>();
try {
//创建存放合并文件 根据需求修改
String path = "D:\\test\\source\\temp";
File mkdir = new File(path);
if (!mkdir.exists()) {
mkdir.mkdirs();
}
file.transferTo(new File(path+"\\"+fileName+"-"+part));
map.put("code",200);
map.put("path",path);
} catch (Exception e) {
map.put("error",e.getMessage());
}/* */
return map;
}
上传完成后的文件是这样的。
合并文件
/**
* 切割上传完成后,合并文件
* */
@PostMapping("/upload2/mergetFile")
@ResponseBody
public Map<String,Object> mergetFile(String fileName,String path){
Map<String, Object> map = new HashMap<String, Object>();
try {
//合并目标路径 根据需求修改 合并文件名 合并来源路径
merge("D:\\test\\target\\", fileName, path);
map.put("code",200);
} catch (Exception e) {
map.put("error",e.getMessage());
}
return map;
}
public static void merge(String targetPath,String targetFileName,String sourcePath) throws IOException{
File file = new File(sourcePath);
File[] fileArr = file.listFiles();
String[] arr = new String[fileArr.length];
//这里要注意,要按文件上传完成顺序合并,如果没有按顺序合并。最终的文件是损坏的。
for (int i = 0; i < fileArr.length; i++) {
arr[i] = fileArr[i].getPath();
}
//根据最后面的部分 按先后顺序排序
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length-1; j++) {
if(Integer.parseInt(arr[i].substring(arr[i].lastIndexOf("-"),arr[i].length()))
>Integer.parseInt(arr[j].substring(arr[j].lastIndexOf("-"),arr[j].length()))) {
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
File destFile = new File(targetPath+targetFileName);//合并后的文件
InputStream in = null;
OutputStream out = new FileOutputStream(destFile);
try {
byte[] bytes = new byte[1024*1024];
for (String f : arr) {
in = new FileInputStream(f);
System.out.println(f);
int len = -1;
while((len = in.read(bytes))!=-1){
out.write(bytes, 0, len);
}
}
in.close();
out.close();
//删除合并前文件
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}