| | |
| | | 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.framework.file.core.client.FileClient; |
| | | import cn.iocoder.yudao.module.infra.framework.file.core.utils.FilePathUtils; |
| | | import cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils; |
| | | import com.google.common.annotations.VisibleForTesting; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Override |
| | | @SneakyThrows |
| | | public String createFile(byte[] content, String name, String directory, String type) { |
| | | // 1.1 处理 type 为空的情况 |
| | | // 1.1 处理 name 的合法性,禁止携带目录路径 |
| | | name = FilePathUtils.validateFileName(name); |
| | | |
| | | // 1.2.1 处理 type 为空的情况 |
| | | if (StrUtil.isEmpty(type)) { |
| | | type = FileTypeUtils.getMineType(content, name); |
| | | } |
| | | // 1.2 处理 name 为空的情况 |
| | | // 1.2.2 处理 name 为空的情况 |
| | | if (StrUtil.isEmpty(name)) { |
| | | name = DigestUtil.sha256Hex(content); |
| | | } |
| | |
| | | |
| | | @VisibleForTesting |
| | | String generateUploadPath(String name, String directory) { |
| | | // 1. 生成前缀、后缀 |
| | | // 1.1 处理 name 和 directory 的合法性 |
| | | name = FilePathUtils.validateFileName(name); |
| | | FilePathUtils.validatePath(name); |
| | | FilePathUtils.validateDirectory(directory); |
| | | // 1.2 生成前缀、后缀 |
| | | String prefix = null; |
| | | if (PATH_PREFIX_DATE_ENABLE) { |
| | | prefix = LocalDateTimeUtil.format(LocalDateTimeUtil.now(), PURE_DATE_PATTERN); |
| | |
| | | |
| | | @Override |
| | | public Long createFile(FileCreateReqVO createReqVO) { |
| | | // 1.1 校验参数的合法性 |
| | | FilePathUtils.validatePath(createReqVO.getPath()); |
| | | createReqVO.setName(FilePathUtils.validateFileName(createReqVO.getName())); |
| | | // 1.2 处理 URL 的合法性,移除 URL 中的查询参数(例如签名参数),保证 URL 的唯一性 |
| | | createReqVO.setUrl(HttpUtils.removeUrlQuery(createReqVO.getUrl())); // 目的:移除私有桶情况下,URL 的签名参数 |
| | | |
| | | // 2. 保存到数据库 |
| | | FileDO file = BeanUtils.toBean(createReqVO, FileDO.class); |
| | | fileMapper.insert(file); |
| | | return file.getId(); |
| | |
| | | |
| | | @Override |
| | | public void deleteFile(Long id) throws Exception { |
| | | // 校验存在 |
| | | // 1.1 校验存在 |
| | | FileDO file = validateFileExists(id); |
| | | // 1.2 校验路径合法性,避免误删文件存储器中的其他文件 |
| | | FilePathUtils.validatePath(file.getPath()); |
| | | |
| | | // 从文件存储器中删除 |
| | | // 2.1 从文件存储器中删除 |
| | | FileClient client = fileConfigService.getFileClient(file.getConfigId()); |
| | | Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId()); |
| | | client.delete(file.getPath()); |
| | | |
| | | // 删除记录 |
| | | // 2.2 删除记录 |
| | | fileMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | // 删除文件 |
| | | List<FileDO> files = fileMapper.selectByIds(ids); |
| | | for (FileDO file : files) { |
| | | FilePathUtils.validatePath(file.getPath()); |
| | | // 获取客户端 |
| | | FileClient client = fileConfigService.getFileClient(file.getConfigId()); |
| | | Assert.notNull(client, "客户端({}) 不能为空", file.getPath()); |
| | |
| | | |
| | | @Override |
| | | public byte[] getFileContent(Long configId, String path) throws Exception { |
| | | // 1. 校验路径合法性 |
| | | FilePathUtils.validatePath(path); |
| | | |
| | | // 2.1 获取客户端 |
| | | FileClient client = fileConfigService.getFileClient(configId); |
| | | Assert.notNull(client, "客户端({}) 不能为空", configId); |
| | | // 2.2 获取文件内容 |
| | | return client.getContent(path); |
| | | } |
| | | |
| | | @Override |
| | | public FileDO getFileByConfigIdAndPath(Long configId, String path) { |
| | | return fileMapper.selectLatestByConfigIdAndPath(configId, path); |
| | | } |
| | | |
| | | } |