|
|
@@ -3,7 +3,7 @@ package cn.reghao.dfs.store.service;
|
|
|
import cn.reghao.dfs.store.model.dto.*;
|
|
|
import cn.reghao.jutil.jdk.security.DigestUtil;
|
|
|
import cn.reghao.dfs.store.model.vo.FileMap;
|
|
|
-import cn.reghao.dfs.store.model.vo.UploadFilePartRet;
|
|
|
+import cn.reghao.dfs.store.model.vo.FilePartRet;
|
|
|
import cn.reghao.dfs.store.model.vo.UploadFileRet;
|
|
|
import cn.reghao.dfs.store.model.vo.UploadPrepareRet;
|
|
|
import cn.reghao.dfs.store.db.repository.FileRepository;
|
|
|
@@ -28,8 +28,8 @@ import java.util.Set;
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
public class FileUploadService {
|
|
|
- // 10MiB
|
|
|
- private final static long PART_SIZE = 1024*1024*10;
|
|
|
+ // 20MiB
|
|
|
+ private final static long PART_SIZE = 1024*1024*20;
|
|
|
|
|
|
private final FileUrlService fileUrlService;
|
|
|
private final FileStoreService fileStoreService;
|
|
|
@@ -51,31 +51,16 @@ public class FileUploadService {
|
|
|
String sha256sum = uploadPrepare.getSha256sum();
|
|
|
FileInfo fileInfo = fileRepository.getFileInfo(sha256sum);
|
|
|
if (fileInfo == null) {
|
|
|
- String uploadId = fileRepository.createFileUploadId(uploadPrepare);
|
|
|
+ String filename = uploadPrepare.getFilename();
|
|
|
+ FileContentType fileContentType = fileTypeService.getFileType(filename);
|
|
|
+ String uploadId = fileRepository.createFileUploadId(uploadPrepare, fileContentType);
|
|
|
return new UploadPrepareRet(uploadId, PART_SIZE, false);
|
|
|
}
|
|
|
|
|
|
String uploadId = fileRepository.getOrCreateUploadId(fileInfo.getFileId());
|
|
|
// uploaded 为 true 则 exist 也应该为 true, 但这里统一将 exist 设置为 false, 表示客户端总是要传输文件流
|
|
|
boolean uploaded = fileInfo.getUploaded();
|
|
|
- return new UploadPrepareRet(uploadId, PART_SIZE, false);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将文件存放到 FileStore,并在数据库中记录文件相关信息
|
|
|
- *
|
|
|
- * @param
|
|
|
- * @return
|
|
|
- * @date 2021-12-08 下午3:30
|
|
|
- */
|
|
|
- public PathUrl putFile(UploadFile uploadFile) throws Exception {
|
|
|
- String uploadId = uploadFile.getUploadId();
|
|
|
- FileInfo fileInfo = fileRepository.getFileInfoByUploadId(uploadId);
|
|
|
- if (!fileInfo.getUploaded()) {
|
|
|
- return put(uploadFile.getFile(), fileInfo, uploadId);
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
+ return new UploadPrepareRet(uploadId, PART_SIZE, true);
|
|
|
}
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@@ -91,13 +76,6 @@ public class FileUploadService {
|
|
|
String fileId = fileInfo.getFileId();
|
|
|
String suffix = fileInfo.getSuffix();
|
|
|
PathUrl pathUrl = fileUrlService.genPathUrl(contentType, sha256sum, size, fileId, suffix, uploadId);
|
|
|
-
|
|
|
- /*if (contentType != null && contentType.startsWith("image")) {
|
|
|
- ImageOps.Size size1 = ImageOps.info(new ByteArrayInputStream(bytes));
|
|
|
- fileUrlService.getImagePathAndUrl(sha256sum, uploadId, size, fileId, suffix,
|
|
|
- size1.getWidth(), size1.getHeight());
|
|
|
- }*/
|
|
|
-
|
|
|
FileContentType fileType = fileTypeService.getFileType(contentType, pathUrl.getAbsolutePath());
|
|
|
try {
|
|
|
fileStoreService.saveFile(pathUrl.getAbsolutePath(), bytes);
|
|
|
@@ -124,14 +102,14 @@ public class FileUploadService {
|
|
|
} else {
|
|
|
int size = bytes.length;
|
|
|
String filename = uploadedFile.getFilename();
|
|
|
+ FileContentType fileContentType = fileTypeService.getFileType(filename);
|
|
|
String suffix = StringUtil.getSuffix(filename);
|
|
|
String contentType = uploadedFile.getContentType();
|
|
|
- FileMap fileMap = fileRepository.createUploadId(uploadedFile, sha256sum, size);
|
|
|
+ FileMap fileMap = fileRepository.createUploadId(filename, sha256sum, size, fileContentType);
|
|
|
|
|
|
String fileId = fileMap.getFileId();
|
|
|
String uploadId = fileMap.getUploadId();
|
|
|
PathUrl pathUrl = fileUrlService.genPathUrl(contentType, sha256sum, size, fileId, suffix, uploadId);
|
|
|
- FileContentType fileType = fileTypeService.getFileType(contentType, pathUrl.getAbsolutePath());
|
|
|
try {
|
|
|
fileStoreService.saveFile(pathUrl.getAbsolutePath(), bytes);
|
|
|
LocalStores.getStoreDir(pathUrl.getAbsolutePath()).incrCount();
|
|
|
@@ -140,44 +118,7 @@ public class FileUploadService {
|
|
|
throw e;
|
|
|
}
|
|
|
|
|
|
- fileRepository.saveFile(fileId, fileType, pathUrl);
|
|
|
- String url = pathUrl.getUrl();
|
|
|
- return new UploadFileRet(uploadId, url);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Deprecated
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public synchronized UploadFileRet put(UploadedFile uploadedFile, String currentUserId) throws Exception {
|
|
|
- byte[] bytes = uploadedFile.getInputStream().readAllBytes();
|
|
|
- String sha256sum = DigestUtil.sha256sum(bytes);
|
|
|
- FileInfo fileInfo = fileRepository.getFileInfo(sha256sum);
|
|
|
- if (fileInfo != null) {
|
|
|
- String fileId = fileInfo.getFileId();
|
|
|
- String uploadId = fileRepository.getOrCreateUploadId(fileInfo.getFileId(), currentUserId);
|
|
|
- String url = fileRepository.getPathUrlByFileId(fileId);
|
|
|
- return new UploadFileRet(uploadId, url);
|
|
|
- } else {
|
|
|
- int size = bytes.length;
|
|
|
- String filename = uploadedFile.getFilename();
|
|
|
- String suffix = StringUtil.getSuffix(filename);
|
|
|
- String contentType = uploadedFile.getContentType();
|
|
|
- FileMap fileMap = fileRepository.createUploadId(uploadedFile, sha256sum, size, currentUserId);
|
|
|
-
|
|
|
- String fileId = fileMap.getFileId();
|
|
|
- String uploadId = fileMap.getUploadId();
|
|
|
- PathUrl pathUrl = fileUrlService.genPathUrl(contentType, sha256sum, size, fileId, suffix, uploadId);
|
|
|
- String absolutePath = pathUrl.getAbsolutePath();
|
|
|
- FileContentType fileType = fileTypeService.getFileType(contentType, absolutePath);
|
|
|
- try {
|
|
|
- fileStoreService.saveFile(absolutePath, bytes);
|
|
|
- LocalStores.getStoreDir(absolutePath).incrCount();
|
|
|
- } catch (Exception e) {
|
|
|
- LocalStores.getStoreDir(absolutePath).decrCount();
|
|
|
- throw e;
|
|
|
- }
|
|
|
-
|
|
|
- fileRepository.saveFile(fileId, fileType, pathUrl);
|
|
|
+ fileRepository.saveFile(fileId, fileContentType, pathUrl);
|
|
|
String url = pathUrl.getUrl();
|
|
|
return new UploadFileRet(uploadId, url);
|
|
|
}
|
|
|
@@ -191,46 +132,50 @@ public class FileUploadService {
|
|
|
* @date 2021-12-08 下午3:31
|
|
|
*/
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public synchronized UploadFilePartRet putFilePart(UploadFilePart uploadFilePart) throws Exception {
|
|
|
- int partIndex = uploadFilePart.getSplitIndex();
|
|
|
- int partNum = uploadFilePart.getSplitNum();
|
|
|
+ public synchronized FilePartRet putFilePart(UploadFilePart uploadFilePart) throws Exception {
|
|
|
+ int partIndex = uploadFilePart.getChunkNumber();
|
|
|
+ int partNum = uploadFilePart.getTotalChunks();
|
|
|
MultipartFile multipartFile = uploadFilePart.getFile();
|
|
|
- String uploadId = uploadFilePart.getUploadId();
|
|
|
+ String uploadId = uploadFilePart.getIdentifier();
|
|
|
FileInfo fileInfo = fileRepository.getFileInfoByFileId(uploadId);
|
|
|
// 没有检查文件的 sha256sum, 存在安全隐患
|
|
|
if (fileInfo.getUploaded()) {
|
|
|
- return new UploadFilePartRet(uploadId, true);
|
|
|
+ return new FilePartRet(uploadId, null);
|
|
|
}
|
|
|
|
|
|
String fileId = fileInfo.getFileId();
|
|
|
String sha256sum = fileInfo.getSha256sum();
|
|
|
String suffix = fileInfo.getSuffix();
|
|
|
- @Deprecated
|
|
|
- PathUrl pathUrl = fileUrlService.genPathAndUrl(sha256sum, 0, fileId, suffix, null);
|
|
|
+ String contentType = fileInfo.getContentType();
|
|
|
+ long size = fileInfo.getSize();
|
|
|
+ PathUrl pathUrl = fileUrlService.genPathUrl(contentType, sha256sum, size, fileId, suffix, uploadId);
|
|
|
Set<Integer> set = map.computeIfAbsent(fileId, k -> new HashSet<>());
|
|
|
+ if (set.isEmpty()) {
|
|
|
+ fileStoreService.createSparseFile(pathUrl.getAbsolutePath(), size);
|
|
|
+ }
|
|
|
+
|
|
|
if (!set.contains(partIndex)) {
|
|
|
set.add(partIndex);
|
|
|
- long size = fileInfo.getSize();
|
|
|
- File file = fileStoreService.createFile(pathUrl.getAbsolutePath(), size);
|
|
|
- long pos = partIndex * PART_SIZE;
|
|
|
- fileStoreService.writeToFile(multipartFile.getInputStream(), file, pos);
|
|
|
+ long pos = (partIndex-1) * PART_SIZE;
|
|
|
+ String absolutePath = pathUrl.getAbsolutePath();
|
|
|
+ fileStoreService.writeToFile(multipartFile.getInputStream(), absolutePath, pos);
|
|
|
}
|
|
|
|
|
|
long len = set.size();
|
|
|
if (len != partNum) {
|
|
|
- return new UploadFilePartRet(fileId, false);
|
|
|
+ return new FilePartRet(fileId);
|
|
|
} else {
|
|
|
- String path = pathUrl.getAbsolutePath();
|
|
|
- FileInputStream fis = new FileInputStream(path);
|
|
|
+ String absolutePath = pathUrl.getAbsolutePath();
|
|
|
+ FileInputStream fis = new FileInputStream(absolutePath);
|
|
|
String sha256sumMerged = DigestUtil.sha256sum(fis);
|
|
|
if (!sha256sum.equals(sha256sumMerged)) {
|
|
|
- throw new Exception("uploadId 和 sha256sum 不匹配!");
|
|
|
+ throw new Exception("分片合并文件的 sha256sum 与原文件一致!");
|
|
|
}
|
|
|
|
|
|
- FileContentType fileType = fileTypeService.getFileType(fileInfo.getContentType(), pathUrl.getAbsolutePath());
|
|
|
+ FileContentType fileType = fileTypeService.getFileType(fileInfo.getContentType(), absolutePath);
|
|
|
fileRepository.saveFile(fileId, fileType, pathUrl);
|
|
|
map.remove(fileId);
|
|
|
- return new UploadFilePartRet(uploadId, true);
|
|
|
+ return new FilePartRet(uploadId, pathUrl);
|
|
|
}
|
|
|
}
|
|
|
}
|