文件分片上传及断点续传
程序员文章站
2024-02-19 10:57:52
...
文件分片上传及断点续传功能
package com.test.file.Upload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Arrays;
import java.util.List;
@Service
public class UploadServiceImpl implements UploadService{
private final static String utf8="utf-8";
public String upload(HttpServletRequest request, HttpServletResponse response) {
//分片
response.setCharacterEncoding(utf8);
//当前分片数
Integer schunk=null;
//总分片数
Integer schunks=null;
//文件名
String name=null;
//文件临时存储目录
String uploadPath="C://files";
//流操作
BufferedOutputStream os=null;
try {
//初始化DiskFileItemFactory,设置一些参数
DiskFileItemFactory factory=new DiskFileItemFactory();
//设置缓冲区,文件先写入内存,再写入磁盘,缓冲区就是内存空间
factory.setSizeThreshold(1024);
//设置临时目录
factory.setRepository(new File(uploadPath));
//解析HttpServletRequest使用,因为所以信息都在HttpServletRequest里面
ServletFileUpload upload=new ServletFileUpload(factory);
//设置单个文件大小
upload.setFileSizeMax(50l*1024l*1024l);
//设置总文件大小
upload.setSizeMax(10000l*1024l*1024l);
//解析HttpServletRequest
List<FileItem> items = upload.parseRequest(request);
//开始解析文件
for (FileItem item : items) {
//判断当前对象是否为文件对象item.isFormField()为true的话代表当前对象为一个基本表单域,不是文件
if(item.isFormField()){
//是表单域的话可以取出分片信息,判断文件名是否相等
if("chunkNumber".equals(item.getFieldName())){
//拿到分片数
schunk=Integer.parseInt(item.getString(utf8));
}
if("totalChunks".equals(item.getFieldName())){
//拿到总分片数
schunks=Integer.parseInt(item.getString(utf8));
}
if("filename".equals(item.getFieldName())){
//拿到文件名
name=item.getString(utf8);
}
if("identifier".equals(item.getFieldName())){
System.out.println("-------------md5值为:"+item.getString(utf8));
}
}
}
for (FileItem item : items) {
//判断当前对象是否为文件对象item.isFormField()为false代表为文件
if(!item.isFormField()){
//临时目录
String temFileName=name;
//判断文件名不能为空
if(name != null){
//判断文件是否分片schunk为空的话就只有一个文件
if(schunk !=null){
temFileName=schunk+"_"+name;
}
File temFile=new File(uploadPath,temFileName);
//判断文件不存在才写入,假如存在就不写,断点续传
if(!temFile.exists()){
item.write(temFile);
}
}
}
}
//文件合并schunk分片数不能为空才合并,分片数为空代表只要一个文件,没有分片,并且分片数要等于总分片数-1
if(schunk != null && schunk.intValue()==schunks.intValue()){
//写文件
File temFile=new File(uploadPath,name);
//拿到流
os=new BufferedOutputStream(new FileOutputStream(temFile));
//找到所有分片
for(int i=0;i<schunks;i++){
File file=new File(uploadPath,(i+1)+"_"+name);
//判断file是否存在,也就是确保所有分片都已经上传成功
while (!file.exists()){
//不存在休眠100毫秒再判断
Thread.sleep(100);
}
byte[] bytes = FileUtils.readFileToByteArray(file);
//删除临时文件
file.delete();
os.write(bytes);
os.flush();
}
os.flush();
return "上传成功:"+name;
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流操作
try {
if(os!=null){
os.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
return "上传成功:"+name;
}
}