新增同步任务添加接口,以及一些调整
This commit is contained in:
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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(".");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 文档")
|
||||
|
||||
@@ -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("删除成功!");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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("暂不支持跨存储同步文件!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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("当前存储服务不允许重复初始化!");
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 桶名称
|
||||
|
||||
@@ -214,4 +214,9 @@ public class AliYunOssServiceImpl extends AbstractOSSBaseService<AliYunOssParam>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveItem(String startPath, String endPath) {
|
||||
// TODO 移动文件
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,6 +100,11 @@ public class LocalServiceImpl extends AbstractFileBaseService<LocalParam> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveItem(String startPath, String endPath) {
|
||||
// TODO 本地文件移动
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文件列表
|
||||
* @param fileList 文件列表
|
||||
|
||||
@@ -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 数据
|
||||
|
||||
Reference in New Issue
Block a user