总的步骤:
1.上传注册:检查文件是否上传,已上传则直接返回,检查文件上传路径是否存在,不存在则创建
2.分块检查:检查分块文件是否上传,已上传则返回true,未上传则检查上传路径是否存在,不存在则创建.
3.分块上传:将分块文件上传到指定的路径.
4.合并分块:将所有分块文件合并为一个文件,在数据库记录文件信息.
相关知识点:
1.new File的相关知识点:new File():既可以创建文件,又可以创建目录。但切记文件对象创建后,指定的文件或目录不一定物理上存在 。
2.RandomAccessFile类的详解
- 因为RandomAccessFile可以自由访问文件的任意位置,所以如果我们希望只访问文件的部分内容,那就可以使用RandomAccessFile类,中的seek方法指定插入的位置。
3.FileInputstream相关知识点: FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等
- InputStream不可以读取文件,它是一个Abstract的类,根本不可能实例化,是所有输入流的基类。而FileInputStream是InputStream的一个实现类,用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
1.上传注册:
//mkdirs:对当前文件夹的字符串创建文件,创建多级目录。
//exists:判断文件是否存在。
public ResponseResult register(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) {
String fileFloadPath = this.getFileFloadPath(fileMd5);
String filePath = this.getFilePath(fileMd5, fileExt);
File file = new File(filePath);
boolean exists = file.exists();
Optional<MediaFile> optional = mediaFileRepository.findById(fileMd5);
if(exists&& optional.isPresent()){
//文件存在
ExceptionCast.cast(MediaCode.UPLOAD_FILE_REGISTER_EXIST);
}
File fileFolder = new File(fileFloadPath);
if(!fileFolder.exists()){
fileFolder.mkdirs();
}
return new ResponseResult(CommonCode.SUCCESS);
}
2.分块检查
public CheckChunkResult checkchunk(String fileMd5, Integer chunk, Integer chunkSize) {
String chunkFileFloadPath = getChunkFileFloadPath(fileMd5);
File chunkFile= new File(chunkFileFloadPath+chunk);
if(chunkFile.exists()){
return new CheckChunkResult(CommonCode.SUCCESS,true);
}else{
//块文件不存在
return new CheckChunkResult(CommonCode.SUCCESS,false);
}
}
3.上传分块
//上传分块
public ResponseResult uploadchunk(MultipartFile file, String fileMd5, Integer chunk) {
//检查分块目录,如果不存在则要自动创建
//得到分块目录
String chunkFileFloadPath = getChunkFileFloadPath(fileMd5);
//得到分块文件路径
String chunkFilePath=chunkFileFloadPath+chunk;
File chunkFileFolder = new File(chunkFileFloadPath);
//如果不存在则要自动创建
if(!chunkFileFolder.exists()){
chunkFileFolder.mkdirs();
}
InputStream inputStream=null;
FileOutputStream fileOutputStream =null;
try {
inputStream = file.getInputStream();
fileOutputStream = new FileOutputStream(new File(chunkFilePath));
IOUtils.copy(inputStream,fileOutputStream);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseResult(CommonCode.SUCCESS);
}
4.合并分块
//合并分块
public ResponseResult mergechunks(String fileMd5, String fileName, Long fileSize, String mimetype, String fileExt) {
//1、合并所有分块
//得到分块文件的属目录
String chunkFileFloadPath = getChunkFileFloadPath(fileMd5);
File chunkFileFload = new File(chunkFileFloadPath);
File[] fileArray = chunkFileFload.listFiles();
List<File> fileList = Arrays.asList(fileArray);
//创建合并的文件
String filePath = getFilePath(fileMd5, fileExt);
File mergeFile = new File(filePath);
//执行合并
mergeFile= mergeFile(fileList, mergeFile);
if(mergeFile==null){
//合并文件失败
ExceptionCast.cast(MediaCode.MERGE_FILE_FAIL);
}
//2、校验文件的md5值是否和前端传入的md5一样
boolean checkFileMd5 = checkFileMd5(mergeFile, fileMd5);
if(!checkFileMd5){
//校验文件失败
ExceptionCast.cast(MediaCode.MERGE_FILE_CHECKFAIL);
}
//3、将文件的信息写入mongodb
MediaFile mediaFile = new MediaFile();
mediaFile.setFileId(fileMd5);
mediaFile.setFileOriginalName(fileName);
mediaFile.setFileName(fileMd5 + "." +fileExt);
//文件路径保存相对路径
String filePath1 = fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/";
mediaFile.setFilePath(filePath1);
mediaFile.setFileSize(fileSize);
mediaFile.setUploadTime(new Date());
mediaFile.setMimeType(mimetype);
mediaFile.setFileType(fileExt);
//状态为上传成功
mediaFile.setFileStatus("301002");
mediaFileRepository.save(mediaFile);
return new ResponseResult(CommonCode.SUCCESS);
}
其中
//合并文件
private File mergeFile(List<File> fileList,File mergeFile){
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if(Integer.parseInt(o1.getName())>Integer.parseInt(o2.getName())){
return 1;
}
return -1;
}
});
try {
byte[] b = new byte[1024];
RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw");
for(File chunkFile:fileList){
int len =-1;
RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "r");
while((len=raf_read.read(b))!=-1){
raf_write.write(b,0,len);
}
raf_read.close();
}
raf_write.close();
return mergeFile;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}