reghao 2 лет назад
Родитель
Сommit
e9208f8e02
24 измененных файлов с 336 добавлено и 202 удалено
  1. 1 7
      dfs-store/src/main/java/cn/reghao/dfs/store/config/OssProperties.java
  2. 8 10
      dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectGetController.java
  3. 6 9
      dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectMultipartUploadController.java
  4. 22 28
      dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectUploadController.java
  5. 41 0
      dfs-store/src/main/java/cn/reghao/dfs/store/model/constant/UploadChannel.java
  6. 3 3
      dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFile.java
  7. 3 1
      dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFilePart.java
  8. 7 6
      dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFileRet.java
  9. 0 15
      dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadedFileRet.java
  10. 2 2
      dfs-store/src/main/java/cn/reghao/dfs/store/model/vo/ObjectMeta.java
  11. 37 0
      dfs-store/src/main/java/cn/reghao/dfs/store/rpc/MediaUrlServiceImpl.java
  12. 0 26
      dfs-store/src/main/java/cn/reghao/dfs/store/rpc/OssServiceImpl.java
  13. 15 0
      dfs-store/src/main/java/cn/reghao/dfs/store/service/FileStoreService.java
  14. 0 26
      dfs-store/src/main/java/cn/reghao/dfs/store/service/FileUrlService.java
  15. 7 8
      dfs-store/src/main/java/cn/reghao/dfs/store/service/ObjectMultipartUploadService.java
  16. 2 5
      dfs-store/src/main/java/cn/reghao/dfs/store/service/PutObjectService.java
  17. 1 1
      dfs-store/src/main/java/cn/reghao/dfs/store/util/store/LocalStores.java
  18. 2 7
      dfs-store/src/main/resources/application-dev.yml
  19. 2 7
      dfs-store/src/main/resources/application-dev1.yml
  20. 2 7
      dfs-store/src/main/resources/application-test.yml
  21. 22 0
      dfs-store/src/test/java/FileMetaTest.java
  22. 20 29
      oss-sdk/src/main/java/cn/reghao/oss/sdk/ObjectBasicService.java
  23. 85 5
      oss-sdk/src/main/java/cn/reghao/oss/sdk/ObjectMultipartUploadService.java
  24. 48 0
      oss-sdk/src/main/java/cn/reghao/oss/sdk/model/UploadFilePart.java

+ 1 - 7
dfs-store/src/main/java/cn/reghao/dfs/store/config/OssProperties.java

@@ -17,11 +17,5 @@ import java.util.List;
 @ConfigurationProperties(prefix = "oss")
 public class OssProperties {
     private String domain;
-    private int group;
-    private int node;
-    // TODO 修改为 mountedDirs, 表示磁盘挂载的目录
-    private List<String> baseDirs;
-    private String encryptKey;
-    private String metaDir;
-    private String cacheDir;
+    private List<String> mountedDirs;
 }

+ 8 - 10
dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectGetController.java

@@ -23,22 +23,20 @@ public class ObjectGetController {
 
     @RequestMapping(value = "/**", method = RequestMethod.HEAD)
     public void headObject() throws IOException {
-        String uri = ServletUtil.getRequest().getRequestURI();
-        String uri1 = URLDecoder.decode(uri, StandardCharsets.UTF_8);
-
-        String objectName = uri1.replaceFirst("/", "");
+        String objectName = getObjectName();
         getObjectService.headObject(objectName);
     }
 
     @GetMapping(value = "/**")
-    public void getObject(@RequestParam(value = "OSSAccessId", required = false) String ossAccessId,
-                          @RequestParam(value = "Expires", required = false) String expires,
-                          @RequestParam(value = "Signature", required = false) String signature) throws IOException {
+    public void getObject() throws IOException {
+        String objectName = getObjectName();
+        getObjectService.getObject(objectName);
+    }
+
+    private String getObjectName() {
         HttpServletRequest servletRequest = ServletUtil.getRequest();
         String uri = servletRequest.getRequestURI();
         String uri1 = URLDecoder.decode(uri, StandardCharsets.UTF_8);
-
-        String objectName = uri1.replaceFirst("/", "");
-        getObjectService.getObject(objectName);
+        return uri1.replaceFirst("/", "");
     }
 }

+ 6 - 9
dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectMultipartUploadController.java

@@ -1,9 +1,6 @@
 package cn.reghao.dfs.store.controller;
 
-import cn.reghao.dfs.store.model.dto.FilePartRet;
-import cn.reghao.dfs.store.model.dto.UploadFilePart;
-import cn.reghao.dfs.store.model.dto.UploadPrepare;
-import cn.reghao.dfs.store.model.dto.UploadPrepareRet;
+import cn.reghao.dfs.store.model.dto.*;
 import cn.reghao.dfs.store.service.ObjectMultipartUploadService;
 import cn.reghao.jutil.jdk.result.WebResult;
 import org.springframework.http.MediaType;
@@ -25,13 +22,13 @@ public class ObjectMultipartUploadController {
     }
 
     @PostMapping(value = "/", params = {"create"}, produces = MediaType.APPLICATION_JSON_VALUE)
-    public String videoFilePrepare(@Validated UploadPrepare uploadPrepare) {
+    public String create(@Validated UploadPrepare uploadPrepare) {
         UploadPrepareRet uploadPrepareRet = objectMultipartUploadService.prepareUpload(uploadPrepare);
         return WebResult.success(uploadPrepareRet);
     }
 
     @GetMapping(value = "/", params = {"multipart"}, produces = MediaType.APPLICATION_JSON_VALUE)
-    public String uploadedVideoFilePart() {
+    public String getUploadedPart() {
         Map<String, Object> map = new HashMap<>();
         map.put("skipUpload", false);
         map.put("url", "");
@@ -41,9 +38,9 @@ public class ObjectMultipartUploadController {
     }
 
     @PostMapping(value = "/", params = {"multipart"}, produces = MediaType.APPLICATION_JSON_VALUE)
-    public String uploadVideoFile0(@Validated UploadFilePart uploadFilePart) throws Exception {
-        FilePartRet uploadedFileRet = objectMultipartUploadService.putFilePart(uploadFilePart);
-        return WebResult.success(uploadedFileRet);
+    public String uploadPart(@Validated UploadFilePart uploadFilePart) throws Exception {
+        UploadFileRet uploadFileRet = objectMultipartUploadService.putFilePart(uploadFilePart);
+        return WebResult.success(uploadFileRet);
     }
 
     @PostMapping(value = "/", params = {"merge"}, produces = MediaType.APPLICATION_JSON_VALUE)

+ 22 - 28
dfs-store/src/main/java/cn/reghao/dfs/store/controller/ObjectUploadController.java

@@ -1,10 +1,9 @@
 package cn.reghao.dfs.store.controller;
 
-import cn.reghao.dfs.store.model.dto.PostObject;
+import cn.reghao.dfs.store.model.constant.UploadChannel;
+import cn.reghao.dfs.store.model.dto.UploadFile;
 import cn.reghao.dfs.store.service.PutObjectService;
-import cn.reghao.jutil.jdk.converter.ByteHex;
 import cn.reghao.jutil.jdk.result.WebResult;
-import cn.reghao.jutil.jdk.security.Base64Util;
 import cn.reghao.jutil.jdk.security.DigestUtil;
 import cn.reghao.jutil.web.ServletUtil;
 import org.springframework.validation.annotation.Validated;
@@ -17,8 +16,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import java.io.File;
 import java.io.FileInputStream;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
 import java.util.UUID;
 
 /**
@@ -33,44 +31,40 @@ public class ObjectUploadController {
         this.putObjectService = putObjectService;
     }
 
-    @PutMapping(value = "/**")
+    //@PutMapping(value = "/**")
+    @PutMapping(value = "/")
     public String putObject(@RequestBody File file) throws Exception {
         HttpServletRequest servletRequest = ServletUtil.getRequest();
-        String contentMd5 = servletRequest.getHeader("content-md5");
-        String sha256sum = servletRequest.getHeader("x-amz-content-sha256");
+        int channelId = Integer.parseInt(servletRequest.getHeader("x-channel-id"));
+        String sha256sum = servletRequest.getHeader("x-content-sha256sum");
 
         FileInputStream fis = new FileInputStream(file);
-        byte[] md5 = DigestUtil.md5sum(fis.readAllBytes());
-        String md5Hex = ByteHex.bytes2Hex(md5);
-        String md5Base64 = Base64Util.encode(md5);
-        if (!contentMd5.equals(md5Base64)) {
-            return WebResult.failWithMsg("md5 不匹配");
-        }
-
-        fis = new FileInputStream(file);
         String sha256sum1 = DigestUtil.sha256sum(fis);
         if (!sha256sum.equals(sha256sum1)) {
             return WebResult.failWithMsg("sha256sum 不匹配");
         }
 
-        String uri = servletRequest.getRequestURI();
-        String decodedUri = URLDecoder.decode(uri, StandardCharsets.UTF_8);
-        String objectName = decodedUri.replaceFirst("/", "");
+        String objectName = getObjectName(channelId);
         putObjectService.putObject(objectName, file, sha256sum);
+        file.delete();
         return WebResult.success();
     }
 
     @PostMapping(value = "/")
-    public String postObject(@Validated PostObject postObject) throws Exception {
-        MultipartFile multipartFile = postObject.getFile();
-        String tmpPath = String.format("/opt/tmp/tomcat/%s", UUID.randomUUID().toString().replace("-", ""));
-        File tmpFile = new File(tmpPath);
-        multipartFile.transferTo(tmpFile);
+    public String postObject(@Validated UploadFile uploadFile) throws Exception {
+        int channelId = uploadFile.getChannelId();
+        String objectName = getObjectName(channelId);
 
-        /*FileInputStream fis = new FileInputStream(tmpFile);
-        String sha256sum = DigestUtil.sha256sum(fis);
-        putObjectService.putObject(objectName, tmpFile, sha256sum);
-        tmpFile.delete();*/
+        MultipartFile multipartFile = uploadFile.getFile();
+        multipartFile.transferTo(Path.of("/opt/tmp/tomcat/1"));
         return WebResult.success();
     }
+
+    private String getObjectName(int channelId) throws Exception {
+        String prefix = UploadChannel.getPrefix(channelId);
+        if (prefix == null) {
+            throw new Exception("channelId 不合法");
+        }
+        return prefix + UUID.randomUUID().toString().replace("-", "");
+    }
 }

+ 41 - 0
dfs-store/src/main/java/cn/reghao/dfs/store/model/constant/UploadChannel.java

@@ -0,0 +1,41 @@
+package cn.reghao.dfs.store.model.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2023-05-23 10:43:25
+ */
+public enum UploadChannel {
+    // 网盘上传
+    disk(1, "file/"),
+    // 视频上传
+    video(2, "video/playback/"),
+    // 视频封面上传
+    cover(3, "image/cover/"),
+    // 用户头像上传
+    avatar(4, "image/avatar/"),
+    // 用户状态照片上传
+    photo(5, "image/photo/"),
+    // 音频上传
+    audio(6, "audio/playback/");
+
+    private final int code;
+    private final String prefix;
+    UploadChannel(int code, String prefix) {
+        this.code = code;
+        this.prefix = prefix;
+    }
+
+    private static Map<Integer, String> map = new HashMap<>();
+    static {
+        for (UploadChannel channel : UploadChannel.values()) {
+            map.put(channel.code, channel.prefix);
+        }
+    }
+
+    public static String getPrefix(int code) {
+        return map.get(code);
+    }
+}

+ 3 - 3
dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/PostObject.java → dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFile.java

@@ -11,16 +11,16 @@ import java.io.Serializable;
 
 /**
  * @author reghao
- * @date 2022-11-21 10:53:54
+ * @date 2023-05-23 10:03:54
  */
 @NoArgsConstructor
 @Getter
 @Setter
-public class PostObject implements Serializable {
+public class UploadFile implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @NotNull
-    private Boolean xAmzUpload;
+    private Integer channelId;
     @NotNull
     private MultipartFile file;
 }

+ 3 - 1
dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFilePart.java

@@ -17,7 +17,9 @@ import java.io.Serializable;
 public class UploadFilePart implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    private String key;
+    @NotNull
+    private int channelId;
+    private String pid;
     @NotNull
     private MultipartFile file;
     // 文件标识

+ 7 - 6
dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/FilePartRet.java → dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadFileRet.java

@@ -4,22 +4,23 @@ import lombok.Getter;
 
 /**
  * @author reghao
- * @date 2022-04-21 09:32:00
+ * @date 2023-05-23 11:11:32
  */
 @Getter
-public class FilePartRet {
+public class UploadFileRet {
     private final String uploadId;
+    private final String url;
     private final boolean merged;
-    private String url;
 
-    public FilePartRet(String uploadId) {
+    public UploadFileRet(String uploadId) {
         this.uploadId = uploadId;
+        this.url = null;
         this.merged = false;
     }
 
-    public FilePartRet(String uploadId, String url) {
+    public UploadFileRet(String uploadId, String url) {
         this.uploadId = uploadId;
-        this.merged = true;
         this.url = url;
+        this.merged = true;
     }
 }

+ 0 - 15
dfs-store/src/main/java/cn/reghao/dfs/store/model/dto/UploadedFileRet.java

@@ -1,15 +0,0 @@
-package cn.reghao.dfs.store.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * @author reghao
- * @date 2022-07-23 06:21:32
- */
-@AllArgsConstructor
-@Getter
-public class UploadedFileRet {
-    private String videoFileId;
-    private boolean merged;
-}

+ 2 - 2
dfs-store/src/main/java/cn/reghao/dfs/store/model/vo/ObjectMeta.java

@@ -14,9 +14,9 @@ import java.io.Serializable;
 public class ObjectMeta implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    private long size;
-    private String contentType;
     private String objectName;
     private String objectId;
     private String absolutePath;
+    private long size;
+    private String contentType;
 }

+ 37 - 0
dfs-store/src/main/java/cn/reghao/dfs/store/rpc/MediaUrlServiceImpl.java

@@ -0,0 +1,37 @@
+package cn.reghao.dfs.store.rpc;
+
+import cn.reghao.dfs.api.dto.ImageUrl;
+import cn.reghao.dfs.api.dto.VideoUrlDto;
+import cn.reghao.dfs.api.iface.MediaUrlService;
+import cn.reghao.dfs.store.db.mapper.ImageFileMapper;
+import cn.reghao.dfs.store.db.mapper.VideoUrlMapper;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2023-01-12 14:44:02
+ */
+@DubboService
+@Service
+public class MediaUrlServiceImpl implements MediaUrlService {
+    private final ImageFileMapper imageFileMapper;
+    private final VideoUrlMapper videoUrlMapper;
+
+    public MediaUrlServiceImpl(ImageFileMapper imageFileMapper, VideoUrlMapper videoUrlMapper) {
+        this.imageFileMapper = imageFileMapper;
+        this.videoUrlMapper = videoUrlMapper;
+    }
+
+    @Override
+    public ImageUrl getImageUrl(String imageFileId) {
+        return imageFileMapper.findImageUrl(imageFileId);
+    }
+
+    @Override
+    public List<VideoUrlDto> getVideoUrls(String videoFileId, String urlType) {
+        return videoUrlMapper.findVideoUrls(videoFileId, urlType);
+    }
+}

+ 0 - 26
dfs-store/src/main/java/cn/reghao/dfs/store/rpc/OssServiceImpl.java

@@ -1,26 +0,0 @@
-package cn.reghao.dfs.store.rpc;
-
-import cn.reghao.dfs.store.db.mapper.FileMetaMapper;
-
-/**
- * @author reghao
- * @date 2023-01-09 15:35:42
- */
-public class OssServiceImpl {
-    private FileMetaMapper fileMetaMapper;
-
-    public void list() {
-        String bucket = "";
-        String prefix = "abc/d/";
-        String startAfter = "abc/d/e";
-        Integer maxKeys = 10;
-
-        StringBuilder regex = new StringBuilder();
-        regex.append("^").append(prefix).append("([^/])+/?$");
-        if (startAfter.isBlank()) {
-            fileMetaMapper.findAll0(bucket, maxKeys, regex.toString());
-        } else {
-            fileMetaMapper.findAll2(bucket, prefix, startAfter, maxKeys);
-        }
-    }
-}

+ 15 - 0
dfs-store/src/main/java/cn/reghao/dfs/store/service/FileStoreService.java

@@ -1,5 +1,7 @@
 package cn.reghao.dfs.store.service;
 
+import cn.reghao.dfs.store.util.store.LoadBalancer;
+import cn.reghao.dfs.store.util.store.StoreDir;
 import org.apache.commons.io.FileUtils;
 import org.springframework.stereotype.Service;
 
@@ -16,6 +18,19 @@ import static java.nio.file.StandardOpenOption.*;
  */
 @Service
 public class FileStoreService {
+    private final LoadBalancer loadBalancer;
+
+    public FileStoreService(LoadBalancer loadBalancer) {
+        this.loadBalancer = loadBalancer;
+    }
+
+    public String genFilePath(String contentId, long size) {
+        //StoreDir storeDir = loadBalancer.getStoreDir(size, sha256sum);
+        StoreDir storeDir = loadBalancer.getStoreDir(size);
+        String fileDir = storeDir.getAbsoluteDirPath();
+        return String.format("%s/%s", fileDir, contentId);
+    }
+
     public void createSparseFile(String absolutePath, long len) throws IOException {
         File file = new File(absolutePath);
         FileUtils.forceMkdirParent(file);

+ 0 - 26
dfs-store/src/main/java/cn/reghao/dfs/store/service/FileUrlService.java

@@ -1,26 +0,0 @@
-package cn.reghao.dfs.store.service;
-
-import cn.reghao.dfs.store.util.store.LoadBalancer;
-import cn.reghao.dfs.store.util.store.StoreDir;
-import org.springframework.stereotype.Service;
-
-/**
- * @author reghao
- * @date 2022-04-26 15:06:29
- */
-@Service
-@Deprecated
-public class FileUrlService {
-    private final LoadBalancer loadBalancer;
-    
-    public FileUrlService(LoadBalancer loadBalancer) {
-        this.loadBalancer = loadBalancer;
-    }
-
-    public String genFilePath(String contentId, long size) {
-        //StoreDir storeDir = loadBalancer.getStoreDir(size, sha256sum);
-        StoreDir storeDir = loadBalancer.getStoreDir(size);
-        String fileDir = storeDir.getAbsoluteDirPath();
-        return String.format("%s/%s", fileDir, contentId);
-    }
-}

+ 7 - 8
dfs-store/src/main/java/cn/reghao/dfs/store/service/ObjectMultipartUploadService.java

@@ -25,16 +25,14 @@ public class ObjectMultipartUploadService {
     private final static long PART_SIZE = 1024*1024*20;
     private final FileMetaMapper fileMetaMapper;
     private final DataBlockMapper dataBlockMapper;
-    private final FileUrlService fileUrlService;
     private final FileStoreService fileStoreService;
     private final Map<String, Set<Integer>> map = new HashMap<>();
     private final Map<String, PathUrl> pathMap = new HashMap<>();
 
     public ObjectMultipartUploadService(FileMetaMapper fileMetaMapper, DataBlockMapper dataBlockMapper,
-                                        FileUrlService fileUrlService, FileStoreService fileStoreService) {
+                                        FileStoreService fileStoreService) {
         this.fileMetaMapper = fileMetaMapper;
         this.dataBlockMapper = dataBlockMapper;
-        this.fileUrlService = fileUrlService;
         this.fileStoreService = fileStoreService;
     }
 
@@ -58,7 +56,7 @@ public class ObjectMultipartUploadService {
      * @date 2023-05-19 10:27:01
      */
     @Transactional(rollbackFor = Exception.class)
-    public synchronized FilePartRet putFilePart(UploadFilePart uploadFilePart) throws Exception {
+    public synchronized UploadFileRet putFilePart(UploadFilePart uploadFilePart) throws Exception {
         String partSha256sum = uploadFilePart.getPartSha256sum();
         long totalSize = uploadFilePart.getTotalSize();
         long chunkSize = uploadFilePart.getChunkSize();
@@ -71,7 +69,7 @@ public class ObjectMultipartUploadService {
         String sha256sum = uploadFilePart.getIdentifier();
         Set<Integer> set = map.computeIfAbsent(sha256sum, k -> new HashSet<>());
         if (set.isEmpty()) {
-            String absolutePath = fileUrlService.genFilePath(sha256sum, totalSize);
+            String absolutePath = fileStoreService.genFilePath(sha256sum, totalSize);
             fileStoreService.createSparseFile(absolutePath, totalSize);
 
             PathUrl pathUrl = new PathUrl(sha256sum, absolutePath);
@@ -85,7 +83,7 @@ public class ObjectMultipartUploadService {
         }
 
         if (set.size() != totalParts) {
-            return new FilePartRet(sha256sum);
+            return new UploadFileRet(sha256sum);
         } else {
             String absolutePath = pathMap.get(sha256sum).getAbsolutePath();
             FileInputStream fis = new FileInputStream(absolutePath);
@@ -95,7 +93,8 @@ public class ObjectMultipartUploadService {
             }
 
             String objectName1;
-            String pid = uploadFilePart.getKey();
+            int channelId = uploadFilePart.getChannelId();
+            String pid = uploadFilePart.getPid();
             if (pid.equals("0")) {
                 objectName1 = UUID.randomUUID().toString().replace("-", "");
             } else {
@@ -110,7 +109,7 @@ public class ObjectMultipartUploadService {
             map.remove(sha256sum);
             pathMap.remove(sha256sum);
             String url = String.format("https://file.reghao.cn/%s", pid);
-            return new FilePartRet(sha256sum, url);
+            return new UploadFileRet(sha256sum, url);
         }
     }
 

+ 2 - 5
dfs-store/src/main/java/cn/reghao/dfs/store/service/PutObjectService.java

@@ -29,15 +29,13 @@ import java.util.UUID;
 public class PutObjectService {
     private final FileMetaMapper fileMetaMapper;
     private final DataBlockMapper dataBlockMapper;
-    private final FileUrlService fileUrlService;
     private final FileStoreService fileStoreService;
 
     public PutObjectService(FileMetaMapper fileMetaMapper, DataBlockMapper dataBlockMapper,
-                            FileStoreService fileStoreService, FileUrlService fileUrlService) {
+                            FileStoreService fileStoreService) {
         this.fileMetaMapper = fileMetaMapper;
         this.dataBlockMapper = dataBlockMapper;
         this.fileStoreService = fileStoreService;
-        this.fileUrlService = fileUrlService;
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -71,7 +69,6 @@ public class PutObjectService {
             long size = file.length();
             FileInputStream fis = new FileInputStream(file);
             List<DataBlock> blocks = store(sha256sum, size, fis);
-            file.delete();
             int fileType = getFileType(contentType);
             fileMeta = new FileMeta(objectName, objectId, filename, size, fileType, contentType, sha256sum, pid);
 
@@ -130,7 +127,7 @@ public class PutObjectService {
     }
 
     private List<DataBlock> store(String sha256sum, long size, InputStream inputStream) throws IOException {
-        String absolutePath = fileUrlService.genFilePath(sha256sum, size);
+        String absolutePath = fileStoreService.genFilePath(sha256sum, size);
         fileStoreService.saveFile(absolutePath, inputStream);
 
         List<DataBlock> list = new ArrayList<>();

+ 1 - 1
dfs-store/src/main/java/cn/reghao/dfs/store/util/store/LocalStores.java

@@ -24,7 +24,7 @@ public class LocalStores {
     public static void init(OssProperties ossProperties) throws IOException {
         //Map<String, String> blockIdMap = getBlockIdMap();
         Map<String, String> checker = new HashMap<>();
-        for (String baseDir : ossProperties.getBaseDirs()) {
+        for (String baseDir : ossProperties.getMountedDirs()) {
             FileStore fileStore = Files.getFileStore(Path.of(baseDir));
             String fs = fileStore.name();
             String mountedOn = fileStore.toString().replace(fs, "").replace(" ()", "");

+ 2 - 7
dfs-store/src/main/resources/application-dev.yml

@@ -13,10 +13,5 @@ spring:
     password: Dev@123456
 oss:
   domain: oss.reghao.cn
-  group: 0
-  node: 0
-  baseDirs:
-    - /opt/oss/disk/00b989fc-991b-4d4e-959e-9b6e19299b72/
-  encryptKey: 5JCdi68CulSDu0TqD4jR
-  metaDir: /opt/oss/meta
-  cacheDir: /opt/oss/cache
+  mountedDirs:
+    - /opt/oss/disk/00b989fc-991b-4d4e-959e-9b6e19299b72/

+ 2 - 7
dfs-store/src/main/resources/application-dev1.yml

@@ -13,10 +13,5 @@ spring:
     password: Dev@123456
 oss:
   domain: oss.reghao.cn
-  group: 0
-  node: 0
-  baseDirs:
-    - /opt/oss/disk/00b989fc-991b-4d4e-959e-9b6e19299b72/
-  encryptKey: 5JCdi68CulSDu0TqD4jR
-  metaDir: /opt/oss/meta
-  cacheDir: /opt/oss/cache
+  mountedDirs:
+    - /opt/oss/disk/00b989fc-991b-4d4e-959e-9b6e19299b72/

+ 2 - 7
dfs-store/src/main/resources/application-test.yml

@@ -13,10 +13,5 @@ spring:
     password: Test@123456
 oss:
   domain: oss.reghao.cn
-  group: 0
-  node: 0
-  baseDirs:
-    - /opt/oss/disk/13f654c8-af87-4710-aac9-7aa086c99aec/
-  encryptKey: 5JCdi68CulSDu0TqD4jR
-  metaDir: /opt/oss/meta
-  cacheDir: /opt/oss/cache
+  mountedDirs:
+    - /opt/oss/disk/13f654c8-af87-4710-aac9-7aa086c99aec/

+ 22 - 0
dfs-store/src/test/java/FileMetaTest.java

@@ -38,6 +38,28 @@ public class FileMetaTest {
     @Autowired
     DataBlockMapper dataBlockMapper;
 
+    /**
+     * 正则表达式查询测试
+     *
+     * @param
+     * @return
+     * @date 2023-05-23 11:06:07
+     */
+    public void regexpTest() {
+        String bucket = "";
+        String prefix = "abc/d/";
+        String startAfter = "abc/d/e";
+        Integer maxKeys = 10;
+
+        StringBuilder regex = new StringBuilder();
+        regex.append("^").append(prefix).append("([^/])+/?$");
+        if (startAfter.isBlank()) {
+            fileMetaMapper.findAll0(bucket, maxKeys, regex.toString());
+        } else {
+            fileMetaMapper.findAll2(bucket, prefix, startAfter, maxKeys);
+        }
+    }
+
     @Test
     public void test2() {
         int pageSize = 1000;

+ 20 - 29
oss-sdk/src/main/java/cn/reghao/oss/sdk/ObjectBasicService.java

@@ -1,11 +1,15 @@
 package cn.reghao.oss.sdk;
 
+import cn.reghao.jutil.jdk.result.WebResult;
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import com.google.gson.reflect.TypeToken;
 import lombok.extern.slf4j.Slf4j;
 
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Type;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.http.HttpClient;
@@ -13,6 +17,7 @@ import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Supplier;
 
@@ -22,17 +27,11 @@ import java.util.function.Supplier;
  */
 @Slf4j
 public class ObjectBasicService {
-    private String endpoint;
-    private String bucketName;
-    private String accessKeyId;
-    private String accessKeySecret;
-    private HttpClient httpClient = HttpClient.newBuilder().build();
+    private final String endpoint;
+    private final HttpClient httpClient = HttpClient.newBuilder().build();
 
-    public ObjectBasicService(String endpoint, String bucketName) {
+    public ObjectBasicService(String endpoint) {
         this.endpoint = endpoint;
-        this.bucketName = bucketName;
-        this.accessKeyId = "LTAI5t9juYR3sSP3t7fstqyt";
-        this.accessKeySecret = "Tn54Dliyk6ET3nYevum9KGRxrM8Ytt";
     }
 
     public void putObject(String key, File file, Map<String, String> headers)
@@ -46,15 +45,14 @@ public class ObjectBasicService {
         int statusCode = httpResponse.statusCode();
         String body = httpResponse.body();
 
-        /*Type type = new TypeToken<WebResult<RsaPubkey>>(){}.getType();
-        WebResult<RsaPubkey> webResult = JsonConverter.jsonToObject(body, type);
+        Type type = new TypeToken<WebResult<String>>(){}.getType();
+        WebResult<String> webResult = JsonConverter.jsonToObject(body, type);
         if (webResult.getCode() == 0) {
-            RsaPubkey rsaPubkey = webResult.getData();
-            log.info("{} - {}", rsaPubkey.getPubkey(), rsaPubkey.getR());
+            String data = webResult.getData();
+            log.info("{}", data);
         } else {
             log.error("{}", webResult.getMsg());
-        }*/
-        System.out.println();
+        }
     }
 
     public void putObject(String key, InputStream inputStream, Map<String, String> headers)
@@ -78,16 +76,14 @@ public class ObjectBasicService {
     public void postObject(String key, File file, String contentType)
             throws URISyntaxException, IOException, InterruptedException {
         MultiPartBodyPublisher publisher = new MultiPartBodyPublisher()
-                .addPart("key", key)
                 .addPart("file", Paths.get(file.getAbsolutePath()))
-                .addPart("contentType", contentType);
+                .addPart("channelId", 1+"");
+                //.addPart("contentType", contentType);
 
         String api = String.format("%s/", endpoint);
         HttpRequest httpRequest = HttpRequest.newBuilder(new URI(api))
                 .version(HttpClient.Version.HTTP_1_1)
-                //.header("Host", "tnb.oss-cn-chengdu.reghao.xyz")
                 .header("Authorization", "5c34161755e3d8b44e5f165ce1b91ef9")
-                //.header("Content-Length", String.valueOf(file.length()))
                 .header("Content-Type", "multipart/form-data; boundary=" + publisher.getBoundary())
                 .POST(publisher.build())
                 .build();
@@ -104,7 +100,6 @@ public class ObjectBasicService {
                 .build();
 
         HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
-        System.out.println();
     }
 
     public void getObject(String objectName) throws IOException, InterruptedException, URISyntaxException {
@@ -114,16 +109,12 @@ public class ObjectBasicService {
                 .GET()
                 .build();
 
-        HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
-        System.out.println();
-    }
-
-    public void deleteObject() {
-    }
-
-    public void deleteMultipleObjects() {
+        HttpResponse<InputStream> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofInputStream());
     }
 
-    public void putObjectCopy() {
+    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
+        String filePath = "/home/reghao/Downloads/video.mp4";
+        ObjectBasicService objectBasicService = new ObjectBasicService("http://localhost:8010");
+        objectBasicService.postObject("a/b/c", new File(filePath), "");
     }
 }

+ 85 - 5
oss-sdk/src/main/java/cn/reghao/oss/sdk/ObjectMultipartUploadService.java

@@ -1,23 +1,103 @@
 package cn.reghao.oss.sdk;
 
+import cn.reghao.jutil.jdk.io.FilePart;
+import cn.reghao.jutil.jdk.security.DigestUtil;
+import cn.reghao.oss.sdk.model.UploadFilePart;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Path;
+import java.security.NoSuchAlgorithmException;
+
 /**
  * @author reghao
  * @date 2022-12-09 10:45:42
  */
+@Slf4j
 public class ObjectMultipartUploadService {
-    public static void initiateMultipartUpload() {
+    static String endpoint = "http://localhost:8010/";
+    static FilePart filePart = new FilePart();
+    static HttpClient httpClient = HttpClient.newBuilder().build();
+
+    static void create() {
+
     }
 
-    public static void uploadPart() {
+    static void postObject(UploadFilePart uploadFilePart)
+            throws URISyntaxException, IOException, InterruptedException {
+        MultiPartBodyPublisher publisher = new MultiPartBodyPublisher();
+        byte[] bytes = uploadFilePart.getBytes();
+        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        publisher
+                .addPart("file", () -> bais, uploadFilePart.getFilename(), "")
+                //.addPart("file", Path.of("/home/reghao/Downloads/video.mp4"))
+                .addPart("channelId", uploadFilePart.getChannelId()+"")
+                .addPart("pid", uploadFilePart.getPid())
+                .addPart("identifier", uploadFilePart.getIdentifier())
+                .addPart("filename", uploadFilePart.getFilename())
+                .addPart("relativePath", uploadFilePart.getRelativePath())
+                .addPart("totalSize", uploadFilePart.getTotalSize()+"")
+                .addPart("chunkSize", uploadFilePart.getChunkSize()+"")
+                .addPart("currentChunkSize", uploadFilePart.getCurrentChunkSize()+"")
+                .addPart("totalChunks", uploadFilePart.getTotalChunks()+"")
+                .addPart("chunkNumber", uploadFilePart.getChunkNumber()+"")
+                .addPart("partSha256sum", uploadFilePart.getPartSha256sum());
+
+        String authorization = "";
+        String api = "http://localhost:8010/?multipart";
+        HttpRequest httpRequest = HttpRequest.newBuilder(new URI(api))
+                .version(HttpClient.Version.HTTP_1_1)
+                .header("Authorization", authorization)
+                .header("Content-Type", "multipart/form-data; boundary=" + publisher.getBoundary())
+                .POST(publisher.build())
+                .build();
+
+        HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
+        System.out.println();
     }
 
-    public static void completeMultipartUpload() {
+    static void upload(File file) throws IOException, NoSuchAlgorithmException, URISyntaxException, InterruptedException {
+        // 分段大小在 5MB - 5GB 之间,只有最后一个分段才允许小于 5MB,不可避免的
+        int minPartSize = filePart.getPartSize();
+        long len = file.length();
+        long total = len/minPartSize;
+        if (len % minPartSize != 0) {
+            total += 1;
+        }
+
+        UploadFilePart uploadFilePart = getUploadFilePart(file);
+        postObject(uploadFilePart);
+        for (int i = 0; i < total; i++) {
+            int start = i*minPartSize;
+            byte[] part = filePart.getPart(file.getAbsolutePath(), minPartSize, start);
+        }
     }
 
-    public static void abortMultipartUpload() {
+    static UploadFilePart getUploadFilePart(File file) throws IOException, NoSuchAlgorithmException {
+        int channelId = 1;
+        String pid = "0";
+        String identifier = DigestUtil.sha256sum(new FileInputStream(file));
+        String filename = file.getName();
+        String relativePath = file.getAbsolutePath();
+        long totalSize = file.length();
+        long chunkSize = 1024*1024*10;
+        UploadFilePart uploadFilePart = new UploadFilePart(channelId, pid, identifier, filename, relativePath,
+                totalSize, chunkSize, 10);
 
+        uploadFilePart.setBytes(new byte[0]);
+        uploadFilePart.setCurrentChunkSize(1024);
+        uploadFilePart.setChunkNumber(1);
+        uploadFilePart.setPartSha256sum("abcdefg");
+        return uploadFilePart;
     }
 
-    public static void listParts() {
+    public static void main(String[] args) throws Exception {
+        String filePath = "/home/reghao/Downloads/video.mp4";
+        upload(new File(filePath));
     }
 }

+ 48 - 0
oss-sdk/src/main/java/cn/reghao/oss/sdk/model/UploadFilePart.java

@@ -0,0 +1,48 @@
+package cn.reghao.oss.sdk.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author reghao
+ * @date 2022-04-25 10:42:38
+ */
+@Getter
+@Setter
+public class UploadFilePart implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private byte[] bytes;
+    private int channelId;
+    private String pid;
+    // 文件标识
+    private String identifier;
+    private String filename;
+    private String relativePath;
+    // 文件大小
+    private Long totalSize;
+    // 分片文件大小
+    private Long chunkSize;
+    // 当前分片文件大小
+    private Integer currentChunkSize;
+    // 分片文件数量
+    private Integer totalChunks;
+    // 当前分片文件索引
+    private Integer chunkNumber;
+    private String partSha256sum;
+
+    public UploadFilePart(int channelId, String pid, String identifier, String filename, String relativePath,
+                          long totalSize, long chunkSize, int totalChunks) {
+        this.channelId = channelId;
+        this.pid = pid;
+        this.identifier = identifier;
+        this.filename = filename;
+        this.relativePath = relativePath;
+        this.totalSize = totalSize;
+        this.chunkSize = chunkSize;
+        this.totalChunks = totalChunks;
+    }
+}