multipartFile) throws Exception {
if (multipartFile == null || multipartFile.isEmpty()) {
log.error("分片上传分片为空");
return fail("分片上传分片为空");
}
// 存放分片文件的服务器绝对路径 ,例如 D:\\uploadfiles\\2020\\04
String uploadFolder = FileDataTypeUtil.getUploadPathPrefix(fileProperties.getStoragePath());
if (fileUploadDTO.getChunks() == null || fileUploadDTO.getChunks() <= 0) {
//没有分片,按照普通文件上传处理
File file = fileStrategy.upload(multipartFile);
file.setFileMd5(fileUploadDTO.getMd5());
fileService.save(file);
return success(null);
} else {
//为上传的文件准备好对应的位置
java.io.File targetFile = webUploader.getReadySpace(fileUploadDTO, uploadFolder);
if (targetFile == null) {
return fail("分片上传失败");
}
//保存上传文件
multipartFile.transferTo(targetFile);
//封装信息给前端,用于分片合并
FileChunksMergeDTO mergeDTO = new FileChunksMergeDTO();
mergeDTO.setSubmittedFileName(multipartFile.getOriginalFilename());
dozerUtils.map(fileUploadDTO,mergeDTO);
return success(mergeDTO);
}
}
}
第二步:在配置属性类中添加storagePath属性和对于的get、set方法
public String getStoragePath() {
return storagePath;
}
public void setStoragePath(String storagePath) {
this.storagePath = storagePath;
}
//指定分片上传时临时存放目录
private String storagePath ;
第三步:创建WebUploader分片上传工具类
package com.itheima.pinda.file.manager;
import com.itheima.pinda.file.dto.chunk.FileUploadDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.IOException;
/**
* 分片上传工具类
*/
@Service
@Slf4j
public class WebUploader2 {
/**
* 为上传的文件创建对应的保存位置,若上传的是分片,则会创建对应的文件夹结构和tmp文件
*
* @param fileUploadDTO 上传文件的相关信息
* @param path 文件保存根路径
* @return
*/
public java.io.File getReadySpace(FileUploadDTO fileUploadDTO, String path) {
//创建上传文件所需的文件夹
if (!this.createFileFolder(path, false)) {
return null;
}
//将上传的分片保存在此目录中
String fileFolder = fileUploadDTO.getName();
if (fileFolder == null) {
return null;
}
//文件上传路径更新为指定文件信息签名后的临时文件夹,用于后期合并
path += "/" + fileFolder;
if (!this.createFileFolder(path, true)) {
return null;
}
//分片上传,指定当前分片文件的文件名
String newFileName = String.valueOf(fileUploadDTO.getChunk());
return new java.io.File(path, newFileName);
}
/**
* 创建存放分片上传的文件的文件夹
*
* @param file 文件夹路径
* @param hasTmp 是否有临时文件
* @return
*/
private boolean createFileFolder(String file, boolean hasTmp) {
//创建存放分片文件的临时文件夹
java.io.File tmpFile = new java.io.File(file);
if (!tmpFile.exists()) {
try {
tmpFile.mkdirs();
} catch (SecurityException ex) {
log.error("无法创建文件夹", ex);
return false;
}
}
if (hasTmp) {
//创建临时文件,用来记录上传分片文件的修改时间,用于清理长期未完成的垃圾分片
tmpFile = new java.io.File(file + ".tmp");
if (tmpFile.exists()) {
return tmpFile.setLastModified(System.currentTimeMillis());
} else {
try {
tmpFile.createNewFile();
} catch (IOException ex) {
log.error("无法创建tmp文件", ex);
return false;
}
}
}
return true;
}
}
第四步:修改Nacos配置中心的pd-file-server.yml文件,加入storagePath配置项
5.10.3.3 接口测试
第一步:启动Nacos配置中心
第二步:启动Nginx服务
第三步:启动文件服务
第四步:访问分片上传页面,进行大文件上传
可以看到,上传完成后,对应的分片上传所需目录、临时文件、分片文件都已经创建成功了:
5.11 接口开发-分片合并
前面我们已经完成了分片上传的接口,本小节需要完成的是将这些分片文件合并为原始文件并按照配置文件配置的存储策略保存到相应位置。由于不同的存储方式对应的分片合并方式也不同,所以我们需要提供不同的分片合并处理策略。具体接口设计如下:
5.11.1 FileChunkStrategy
FileChunkStrategy是分片文件处理策略顶