完成 FileApi 的 feign 支持

This commit is contained in:
YunaiV 2022-06-15 21:05:08 +08:00
parent 4c6e915def
commit 9b3092b3fd
13 changed files with 114 additions and 71 deletions

View File

@ -1,23 +1,32 @@
package cn.iocoder.yudao.module.infra.api.file; package cn.iocoder.yudao.module.infra.api.file;
import cn.hutool.core.util.IdUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.infra.api.file.dto.FileCreateReqDTO;
import cn.iocoder.yudao.module.infra.enums.ApiConstants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/** import javax.validation.Valid;
* 文件 API 接口
* @FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
* @author 芋道源码 @Api(tags = "RPC 服务 - 文件")
*/
public interface FileApi { public interface FileApi {
String PREFIX = ApiConstants.PREFIX + "/file";
/** /**
* 保存文件并返回文件的访问路径 * 保存文件并返回文件的访问路径
* *
* @param content 文件内容 * @param content 文件内容
* @return 文件路径 * @return 文件路径
*/ */
default String createFile(byte[] content) throws Exception { default String createFile(byte[] content) {
return createFile(IdUtil.fastUUID(), content); return createFile(null, null, content);
} }
/** /**
* 保存文件并返回文件的访问路径 * 保存文件并返回文件的访问路径
@ -26,6 +35,28 @@ public interface FileApi {
* @param content 文件内容 * @param content 文件内容
* @return 文件路径 * @return 文件路径
*/ */
String createFile(String path, byte[] content) throws Exception; default String createFile(String path, byte[] content) {
return createFile(null, path, content);
}
/**
* 保存文件并返回文件的访问路径
*
* @param name 原文件名称
* @param path 文件路径
* @param content 文件内容
* @return 文件路径
*/
default String createFile(@RequestParam("name") String name,
@RequestParam("path") String path,
@RequestParam("content") byte[] content) {
CommonResult<String> result = createFile(new FileCreateReqDTO().setName(name).setPath(path).setContent(content));
result.checkError();
return result.getData();
}
@PostMapping(PREFIX + "/create")
@ApiOperation("保存文件,并返回文件的访问路径")
CommonResult<String> createFile(@Valid @RequestBody FileCreateReqDTO createReqDTO);
} }

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.infra.api.file.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@ApiModel("RPC 服务 - 文件创建 Request DTO")
@Data
public class FileCreateReqDTO {
@ApiModelProperty(value = "原文件名称", example = "xxx.png")
private String name;
@ApiModelProperty(value = "文件路径", example = "xxx.png")
private String path;
@ApiModelProperty(value = "文件内容", required = true)
@NotEmpty(message = "文件内容不能为空")
private byte[] content;
}

View File

@ -7,7 +7,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.Date; import java.util.Date;
@ApiModel("API 错误日志创建 Request DTO") @ApiModel("RPC 服务 - API 错误日志创建 Request DTO")
@Data @Data
public class ApiErrorLogCreateReqDTO { public class ApiErrorLogCreateReqDTO {

View File

@ -1,17 +1,22 @@
package cn.iocoder.yudao.module.infra.api.file; package cn.iocoder.yudao.module.infra.api.file;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.infra.api.file.dto.FileCreateReqDTO;
import cn.iocoder.yudao.module.infra.service.file.FileService; import cn.iocoder.yudao.module.infra.service.file.FileService;
import org.apache.commons.fileupload.FileItem;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
/** import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
* 文件 API 实现类 import static cn.iocoder.yudao.module.system.enums.ApiConstants.VERSION;
*
* @author 芋道源码 @RestController // 提供 RESTful API 接口 Feign 调用
*/ @DubboService(version = VERSION) // 提供 Dubbo RPC 接口 Dubbo Consumer 调用
@Service
@Validated @Validated
public class FileApiImpl implements FileApi { public class FileApiImpl implements FileApi {
@ -19,8 +24,9 @@ public class FileApiImpl implements FileApi {
private FileService fileService; private FileService fileService;
@Override @Override
public String createFile(String path, byte[] content) throws Exception { public CommonResult<String> createFile(FileCreateReqDTO createReqDTO) {
return fileService.createFile(path, content); return success(fileService.createFile(createReqDTO.getName(), createReqDTO.getPath(),
createReqDTO.getContent()));
} }
} }

View File

@ -46,7 +46,7 @@ public class FileController {
@OperateLog(logArgs = false) // 上传文件没有记录操作日志的必要 @OperateLog(logArgs = false) // 上传文件没有记录操作日志的必要
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file, public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam(value = "path", required = false) String path) throws Exception { @RequestParam(value = "path", required = false) String path) throws Exception {
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream()))); return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
} }
@DeleteMapping("/delete") @DeleteMapping("/delete")

View File

@ -33,6 +33,10 @@ public class FileDO extends BaseDO {
* 关联 {@link FileConfigDO#getId()} * 关联 {@link FileConfigDO#getId()}
*/ */
private Long configId; private Long configId;
/**
* 原文件名
*/
private String name;
/** /**
* 路径即文件名 * 路径即文件名
*/ */

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.infra.service.file; package cn.iocoder.yudao.module.infra.service.file;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
/** /**
@ -22,11 +22,12 @@ public interface FileService {
/** /**
* 保存文件并返回文件的访问路径 * 保存文件并返回文件的访问路径
* *
* @param name 原文件名称
* @param path 文件路径 * @param path 文件路径
* @param content 文件内容 * @param content 文件内容
* @return 文件路径 * @return 文件路径
*/ */
String createFile(String path, byte[] content) throws Exception; String createFile(String name, String path, byte[] content);
/** /**
* 删除文件 * 删除文件

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.file.core.client.FileClient;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -37,12 +38,17 @@ public class FileServiceImpl implements FileService {
} }
@Override @Override
public String createFile(String path, byte[] content) throws Exception { @SneakyThrows
public String createFile(String name, String path, byte[] content) {
// 计算默认的 path // 计算默认的 path
String type = FileTypeUtil.getType(new ByteArrayInputStream(content), path); String type = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
if (StrUtil.isEmpty(path)) { if (StrUtil.isEmpty(path)) {
path = DigestUtil.md5Hex(content) + '.' + type; path = DigestUtil.md5Hex(content) + '.' + type;
} }
// 如果 name 为空则使用 path 填充
if (StrUtil.isEmpty(name)) {
name = path;
}
// 上传到文件存储器 // 上传到文件存储器
FileClient client = fileConfigService.getMasterFileClient(); FileClient client = fileConfigService.getMasterFileClient();
@ -52,6 +58,7 @@ public class FileServiceImpl implements FileService {
// 保存到数据库 // 保存到数据库
FileDO file = new FileDO(); FileDO file = new FileDO();
file.setConfigId(client.getId()); file.setConfigId(client.getId());
file.setName(name);
file.setPath(path); file.setPath(path);
file.setUrl(url); file.setUrl(url);
file.setType(type); file.setType(type);

View File

@ -80,9 +80,9 @@ public class FileServiceTest extends BaseDbUnitTest {
String url = randomString(); String url = randomString();
when(client.upload(same(content), same(path))).thenReturn(url); when(client.upload(same(content), same(path))).thenReturn(url);
when(client.getId()).thenReturn(10L); when(client.getId()).thenReturn(10L);
String name = "单测文件名";
// 调用 // 调用
String result = fileService.createFile(path, content); String result = fileService.createFile(name, path, content);
// 断言 // 断言
assertEquals(result, url); assertEquals(result, url);
// 校验数据 // 校验数据

View File

@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
@ApiModel("操作日志创建 Request DTO") @ApiModel("RPC 服务 - 操作日志创建 Request DTO")
@Data @Data
public class OperateLogCreateReqDTO { public class OperateLogCreateReqDTO {

View File

@ -1,44 +0,0 @@
package cn.iocoder.yudao.module.system.framework;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TmpConfiguration {
@Bean
public FileApi fileApi() {
return new FileApi() {
@Override
public String createFile(String path, byte[] content) throws Exception {
return null;
}
};
}
@Bean
public ApiAccessLogFrameworkService apiAccessLogFrameworkService() {
return new ApiAccessLogFrameworkService() {
@Override
public void createApiAccessLog(ApiAccessLog apiAccessLog) {
}
};
}
@Bean
public ApiErrorLogFrameworkService apiErrorLogFrameworkService() {
return new ApiErrorLogFrameworkService() {
@Override
public void createApiErrorLog(ApiErrorLog apiErrorLog) {
}
};
}
}

View File

@ -0,0 +1,11 @@
package cn.iocoder.yudao.module.system.framework.rpc.config;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = FileApi.class)
public class RpcConfiguration {
}

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.system.framework.rpc;