新增同步任务添加接口,以及一些调整

This commit is contained in:
besscroft
2023-03-23 22:13:48 +08:00
parent 6b8e7f561f
commit 003b7c5b94
15 changed files with 222 additions and 2 deletions

View File

@@ -0,0 +1,31 @@
package com.besscroft.diyfile.common.param.sync;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @Description 同步任务参数
* @Author Bess Croft
* @Date 2023/3/21 21:28
*/
@Data
@Schema(title = "同步任务参数")
public class SyncTaskParam {
/** 同步前存储 key */
@Schema(title = "同步前存储 key", type = "String")
private String beforeStorageKey;
/** 同步前的路径(文件夹或文件相对路径) */
@Schema(title = "同步前的路径(文件夹或文件相对路径)", type = "String")
private String beforePath;
/** 同步后存储 key */
@Schema(title = "同步后存储 key", type = "String")
private String afterStorageKey;
/** 同步后的路径(文件夹相对路径) */
@Schema(title = "同步后的路径(文件夹相对路径)", type = "String")
private String afterPath;
}

View File

@@ -1,6 +1,8 @@
package com.besscroft.diyfile.common.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.besscroft.diyfile.common.exception.DiyFileException;
/**
* @Description 路径处理工具类
@@ -34,4 +36,26 @@ public class PathUtils {
return URLUtil.decode(path);
}
/**
* 异常路径处理
*/
public static void checkPath(String path) {
if (StrUtil.containsAll(path, "../", "./")) {
throw new DiyFileException("路径不合法!");
}
}
/**
* 判断路径为文件还是文件夹
* @param path 路径
* @return true 文件夹 false 文件
*/
public static boolean isFolder(String path) {
// 不包含扩展名的 . 肯定为文件夹
if (!StrUtil.contains(path, ".") || StrUtil.equals(path, "/")) return true;
int lastSlashIndex = path.lastIndexOf('/');
String realPath = path.substring(lastSlashIndex + 1);
return !realPath.contains(".");
}
}

View File

@@ -20,7 +20,7 @@ public class OpenApiConfiguration {
return new OpenAPI()
.info(new Info().title("DiyFile")
.description("一款好看的在线文件列表程序")
.version("v0.3.1")
.version("v0.3.2")
.license(new License().name("MIT license").url("https://github.com/besscroft/diyfile/blob/main/LICENSE")))
.externalDocs(new ExternalDocumentation()
.description("DiyFile 文档")

View File

@@ -10,6 +10,7 @@ import com.besscroft.diyfile.common.param.file.GetItemByKeyParam;
import com.besscroft.diyfile.common.param.file.GetUploadUrlParam;
import com.besscroft.diyfile.common.result.AjaxResult;
import com.besscroft.diyfile.common.result.CommonResult;
import com.besscroft.diyfile.common.util.PathUtils;
import com.besscroft.diyfile.common.vo.FileInfoVo;
import com.besscroft.diyfile.common.vo.StorageInfoVo;
import com.besscroft.diyfile.service.FileService;
@@ -53,6 +54,8 @@ public class FileController {
@GetMapping("/getItem")
public CommonResult<List<FileInfoVo>> base(@RequestParam(value = "storageId") Long storageId,
@RequestParam(value = "folderPath") String folderPath) {
// 校验路径
PathUtils.checkPath(folderPath);
return CommonResult.success(fileService.getItem(storageId, folderPath));
}
@@ -60,6 +63,8 @@ public class FileController {
@Operation(summary = "首页文件列表")
@PostMapping("/getItemByKey")
public CommonResult<List<FileInfoVo>> baseByKey(@RequestBody @Valid GetItemByKeyParam param) {
// 校验路径
PathUtils.checkPath(param.getFolderPath());
return CommonResult.success(fileService.getItemByKey(param.getStorageKey(), param.getFolderPath()));
}
@@ -67,6 +72,8 @@ public class FileController {
@Operation(summary = "文件信息")
@PostMapping("/getFileInfo")
public CommonResult<FileInfoVo> getFileInfo(@RequestBody GetFileInfoParam param) {
// 校验路径
PathUtils.checkPath(param.getFilePath());
return CommonResult.success(fileService.getFileInfo(param.getStorageKey(), param.getFilePath(), param.getFileName()));
}
@@ -95,6 +102,8 @@ public class FileController {
@Operation(summary = "删除文件接口")
@PostMapping("/deleteFile")
public AjaxResult deleteFile(@RequestBody @Valid DeleteFileParam param) {
// 校验路径
PathUtils.checkPath(param.getPath());
fileService.deleteFile(param.getStorageKey(), param.getPath());
return AjaxResult.success("删除成功!");
}

View File

@@ -0,0 +1,40 @@
package com.besscroft.diyfile.controller;
import com.besscroft.diyfile.common.param.sync.SyncTaskParam;
import com.besscroft.diyfile.common.result.AjaxResult;
import com.besscroft.diyfile.common.util.PathUtils;
import com.besscroft.diyfile.service.SyncService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description 存储数据同步
* @Author Bess Croft
* @Date 2023/3/21 21:26
*/
@Tag(name = "存储数据同步")
@RestController
@RequestMapping("/sync")
@RequiredArgsConstructor
public class SyncController {
private final SyncService syncService;
@PostMapping("/taskAdd")
@Operation(summary = "添加同步任务")
public AjaxResult taskAdd(@RequestBody SyncTaskParam param) {
PathUtils.checkPath(param.getBeforePath());
PathUtils.checkPath(param.getAfterPath());
syncService.taskAdd(param.getBeforeStorageKey(),
PathUtils.decode(param.getBeforePath()),
param.getAfterStorageKey(),
PathUtils.decode(param.getAfterPath()));
return AjaxResult.success();
}
}

View File

@@ -0,0 +1,19 @@
package com.besscroft.diyfile.service;
/**
* @Description 存储数据同步服务
* @Author Bess Croft
* @Date 2023/3/21 21:43
*/
public interface SyncService {
/**
* 添加同步任务
* @param beforeStorageKey 同步前存储 key
* @param beforePath 同步前的路径(文件夹或文件相对路径)
* @param afterStorageKey 同步后存储 key
* @param afterPath 同步后的路径(文件夹相对路径)
*/
void taskAdd(String beforeStorageKey, String beforePath, String afterStorageKey, String afterPath);
}

View File

@@ -0,0 +1,48 @@
package com.besscroft.diyfile.service.impl;
import cn.hutool.core.util.StrUtil;
import com.besscroft.diyfile.common.exception.DiyFileException;
import com.besscroft.diyfile.common.param.FileInitParam;
import com.besscroft.diyfile.common.util.PathUtils;
import com.besscroft.diyfile.service.StorageService;
import com.besscroft.diyfile.service.SyncService;
import com.besscroft.diyfile.storage.context.StorageApplicationContext;
import com.besscroft.diyfile.storage.service.base.AbstractFileBaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @Description 存储数据同步服务实现
* @Author Bess Croft
* @Date 2023/3/21 21:44
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SyncServiceImpl implements SyncService {
private final StorageApplicationContext storageApplicationContext;
private final StorageService storageService;
@Override
public void taskAdd(String beforeStorageKey, String beforePath, String afterStorageKey, String afterPath) {
// 判断被同步路径是否为文件夹路径
if (!PathUtils.isFolder(afterPath)) throw new DiyFileException("被同步路径必须为文件夹路径!");
Long beforeStorageId = storageService.getStorageIdByStorageKey(afterStorageKey);
Long afterStorageId = storageService.getStorageIdByStorageKey(afterStorageKey);
log.info("同步任务参数:{} {} {} {}", beforeStorageKey, beforePath, afterStorageKey, afterPath);
// TODO 同步操作
if (StrUtil.equals(beforeStorageKey, afterStorageKey)) {
// 相同存储内移动文件
// 移动文件,调用对应存储 API 移动文件接口
AbstractFileBaseService<FileInitParam> service = storageApplicationContext.getServiceByStorageId(beforeStorageId);
service.moveItem(beforePath, afterPath);
} else {
// 不同存储内移动文件
// TODO 先下载文件,然后上传文件;如果存储 API 支持传递文件流,则直接复用。
throw new DiyFileException("暂不支持跨存储同步文件!");
}
}
}

View File

@@ -79,6 +79,13 @@ public abstract class AbstractFileBaseService<T extends FileInitParam> implement
*/
public abstract String getUploadSession(String folderPath);
/**
* 在驱动器内移动项目,可能是文件或文件夹
* @param startPath 开始路径
* @param endPath 结束路径
*/
public abstract void moveItem(String startPath, String endPath);
public void setStorageId(Long storageId) {
if (Objects.nonNull(this.storageId))
throw new IllegalStateException("当前存储服务不允许重复初始化!");

View File

@@ -17,4 +17,11 @@ public abstract class AbstractOSSBaseService<T extends OssParam> extends Abstrac
*/
public abstract String getObjectUrl(String bucketName, String objectName);
/**
* 在驱动器内移动项目,可能是文件或文件夹
* @param startPath 开始路径
* @param endPath 结束路径
*/
public abstract void moveItem(String startPath, String endPath);
}

View File

@@ -58,6 +58,13 @@ public abstract class AbstractOneDriveBaseService<T extends OneDriveParam> exten
*/
public abstract String getUploadSession(String folderPath);
/**
* 在驱动器内移动项目,可能是文件或文件夹
* @param startPath 开始路径
* @param endPath 结束路径
*/
public abstract void moveItem(String startPath, String endPath);
/**
* 获取 OneDrive 驱动 id
* @return OneDrive 驱动 id

View File

@@ -151,6 +151,11 @@ public abstract class AbstractS3BaseService<T extends S3Param> extends AbstractF
return getObjectUrl(initParam.getBucketName(), PathUtils.removeLeadingSlash(filePath));
}
@Override
public void moveItem(String startPath, String endPath) {
// TODO 移动文件
}
/**
* 获取文件下载地址
* @param bucketName 桶名称

View File

@@ -214,4 +214,9 @@ public class AliYunOssServiceImpl extends AbstractOSSBaseService<AliYunOssParam>
}
}
@Override
public void moveItem(String startPath, String endPath) {
// TODO 移动文件
}
}

View File

@@ -100,6 +100,11 @@ public class LocalServiceImpl extends AbstractFileBaseService<LocalParam> {
return null;
}
@Override
public void moveItem(String startPath, String endPath) {
// TODO 本地文件移动
}
/**
* 处理文件列表
* @param fileList 文件列表

View File

@@ -9,6 +9,7 @@ import com.besscroft.diyfile.common.constant.FileConstants;
import com.besscroft.diyfile.common.constant.storage.OneDriveConstants;
import com.besscroft.diyfile.common.exception.DiyFileException;
import com.besscroft.diyfile.common.param.storage.init.OneDriveParam;
import com.besscroft.diyfile.common.util.PathUtils;
import com.besscroft.diyfile.common.vo.FileInfoVo;
import com.besscroft.diyfile.storage.service.base.AbstractOneDriveBaseService;
import com.ejlchina.okhttps.HttpResult;
@@ -135,6 +136,18 @@ public class OneDriveServiceImpl extends AbstractOneDriveBaseService<OneDrivePar
return result.getStr("uploadUrl");
}
@Override
public void moveItem(String startPath, String endPath) {
// TODO 移动文件,需要先获取 item-id@see https://learn.microsoft.com/zh-cn/graph/api/driveitem-move?view=graph-rest-1.0&tabs=http
if (PathUtils.isFolder(startPath)) {
// TODO 如果为文件夹,则需要递归移动文件夹下的所有文件
} else {
// TODO 如果为文件,则直接移动文件
}
}
/**
* 处理 OneDrive 返回的文件信息 JSON 数据
* @param jsonObject OneDrive 返回的文件信息 JSON 数据

View File

@@ -17,7 +17,7 @@
<packaging>pom</packaging>
<properties>
<revision>0.3.1</revision>
<revision>0.3.2</revision>
<java.version>17</java.version>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>