当前位置: 首页 > news >正文

026-从零搭建微服务-文件服务(二)

写在最前

如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。

源码地址(后端):https://gitee.com/csps/mingyue

源码地址(前端):https://gitee.com/csps/mingyue-ui

文档地址:https://gitee.com/csps/mingyue/wikis

OSS 基础表设计

1. OSS对象存储表

DROP TABLE IF EXISTS sys_oss;
CREATE TABLE sys_oss (oss_id           BIGINT(20)        NOT NULL                   COMMENT 'OSS对象ID',file_name        VARCHAR(255)      NOT NULL DEFAULT ''        COMMENT '文件名',original_name    VARCHAR(255)      NOT NULL DEFAULT ''        COMMENT '原名',file_suffix      VARCHAR(10)       NOT NULL DEFAULT ''        COMMENT '文件后缀名',file_url         VARCHAR(500)      NOT NULL                   COMMENT '文件URL',create_time      DATETIME          DEFAULT NULL               COMMENT '创建时间',create_by        VARCHAR(64)       DEFAULT ''                 COMMENT '上传人',update_time      DATETIME          DEFAULT NULl               COMMENT '更新时间',update_by        VARCHAR(64)       DEFAULT ''                 COMMENT '更新人',service          VARCHAR(20)       NOT NULL DEFAULT 'minio'   COMMENT '服务商',primary key (oss_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='OSS对象存储表';

2. OSS对象存储动态配置表

DROP TABLE IF EXISTS sys_oss_config;
CREATE TABLE sys_oss_config (oss_config_id     BIGINT(20)         NOT NULL                 COMMENT 'OSS动态配置ID',config_key        VARCHAR(20)        NOT NULL DEFAULT ''      COMMENT '配置key',access_key        VARCHAR(255)       DEFAULT ''               COMMENT 'accessKey',secret_key        VARCHAR(255)       DEFAULT ''               COMMENT '秘钥',bucket_name       VARCHAR(255)       DEFAULT ''               COMMENT '桶名称',prefix            VARCHAR(255)       DEFAULT ''               COMMENT '前缀',endpoint          VARCHAR(255)       DEFAULT ''               COMMENT '访问站点',domain            VARCHAR(255)       DEFAULT ''               COMMENT '自定义域名',is_https          CHAR(1)            DEFAULT 'N'              COMMENT '是否https(Y是 N否)',region            VARCHAR(255)       DEFAULT ''               COMMENT '域',access_policy     CHAR(1)            NOT NULL DEFAULT '1'     COMMENT '桶权限类型(0-private 1-public 2-custom)',status            CHAR(1)            DEFAULT '1'              COMMENT '是否默认(0是 1否)',extend            VARCHAR(255)       DEFAULT ''               COMMENT '扩展字段',create_by         VARCHAR(64)        DEFAULT ''               COMMENT '创建者',create_time       DATETIME           DEFAULT NULL             COMMENT '创建时间',update_by         VARCHAR(64)        DEFAULT ''               COMMENT '更新者',update_time       DATETIME           DEFAULT NULL             COMMENT '更新时间',PRIMARY KEY (oss_config_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='OSS对象存储动态配置表';INSERT INTO `sys_oss_config` VALUES (1, 'minio', 'd6zVm5AP07uGCqSmsTxe', 'Vsm6qQDHgGchukEpyEoeX3dTe7fic60nTi8D9a0I', 'mingyue', '', 'mingyue-minio:5000', '', 'N', '', '1', '0', '', 'admin', '2023-09-11 17:50:40', 'admin', '2023-09-11 17:50:40');
COMMIT;

OSS 配置加载

初始化OSS配置

@Override
public void init() {List<SysOssConfig> list = this.list();// 加载 OSS 初始化配置for (SysOssConfig config : list) {String configKey = config.getConfigKey();if ("0".equals(config.getStatus())) {RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);}RedisUtils.setCacheMapValue(OssConstant.SYS_OSS_CONFIG, config.getConfigKey(), JSONUtil.toJsonStr(config));}
}

OssApplicationRunner

@Slf4j
@Component
@RequiredArgsConstructor
public class OssApplicationRunner implements ApplicationRunner {private final SysOssConfigService sysOssConfigService;@Overridepublic void run(ApplicationArguments args) {sysOssConfigService.init();log.info("初始化 OSS 配置成功");}}

改进 OssFactory

@Slf4j
public class OssFactory {private static final Map<String, OssClient> CLIENT_CACHE = new ConcurrentHashMap<>();/*** 获取默认实例*/public static OssClient instance() {// 获取redis 默认类型String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY);if (StrUtil.isEmpty(configKey)) {throw new OssException("文件存储服务类型无法找到!");}return instance(configKey);}/*** 根据类型获取实例*/public static OssClient instance(String configKey) {String json = RedisUtils.getCacheMapValue(OssConstant.SYS_OSS_CONFIG, configKey);if (json == null) {throw new OssException("系统异常, '" + configKey + "'配置信息不存在!");}OssProperties properties = JSONUtil.toBean(json, OssProperties.class);OssClient client = CLIENT_CACHE.get(configKey);if (client == null) {CLIENT_CACHE.put(configKey, new OssClient(configKey, properties));log.info("创建OSS实例 key => {}", configKey);return CLIENT_CACHE.get(configKey);}// 配置不相同则重新构建if (!client.checkPropertiesSame(properties)) {CLIENT_CACHE.put(configKey, new OssClient(configKey, properties));log.info("重载OSS实例 key => {}", configKey);return CLIENT_CACHE.get(configKey);}return client;}}

移除 Nacos OSS 配置

因为从数据库加载配置,所以不在需要 Nacos 配置了

oss:configKey: minioendpoint: mingyue-minio:5000domain:prefix:accessKey: d6zVm5AP07uGCqSmsTxesecretKey: Vsm6qQDHgGchukEpyEoeX3dTe7fic60nTi8D9a0IbucketName: mingyueregion: isHttps: NaccessPolicy: 1

上传测试

{"code": 200,"msg": "操作成功","data": {"ossId": "1701490497677180930","fileName": "2023-09-12/d1b5389a465f4bf7985844916d785c06.png","originalName": "head_1.png","fileSuffix": ".png","fileUrl": "http://mingyue-minio:5000/mingyue/2023-09-12/d1b5389a465f4bf7985844916d785c06.png","createTime": "2023-09-12 14:58:41","createBy": "mingyue","service": "minio"}
}

OSS 上传信息保存

/*** 构建上传文件返回信息* @param originalFilename 原始文件名* @param suffix 文件后缀* @param configKey 配置key* @param uploadResult OSS服务返回结果* @return*/
private SysOssVo buildResult(String originalFilename, String suffix, String configKey, UploadResult uploadResult) {SysOss oss = new SysOss();oss.setFileUrl(uploadResult.getFileUrl());oss.setFileSuffix(suffix);oss.setFileName(uploadResult.getFileName());oss.setOriginalName(originalFilename);oss.setService(configKey);this.save(oss);SysOssVo sysOssVo = BeanUtil.toBean(oss, SysOssVo.class);return this.matchingUrl(sysOssVo);
}

删除文件

逻辑实现

删除数据库记录的同时需要删除OSS服务对应的文件

@Override
public Boolean deleteByOssIds(List<Long> ossIds) {List<SysOss> list = this.listByIds(ossIds);if (CollUtil.isEmpty(list)) {return Boolean.FALSE;}for (SysOss sysOss : list) {OssClient storage = OssFactory.instance(sysOss.getService());storage.delete(sysOss.getFileUrl());}return this.removeBatchByIds(ossIds);
}

删除接口

@DeleteMapping("/{ossIds}")
@Operation(summary = "删除OSS对象存储",parameters = { @Parameter(name = "ossIds", description = "oss对象Ids", required = true) })
public R<Boolean> remove(@NotEmpty(message = "主键不能为空") @PathVariable List<Long> ossIds) {return R.ok(sysOssService.deleteByOssIds(ossIds));
}

删除测试

删除前打开文件查看:http://mingyue-minio:5000/mingyue/2023-09-12/d1b5389a465f4bf7985844916d785c06.png

curl -X 'DELETE' \'http://mingyue-gateway:9100/oss/sysOss/1701490497677180930' \-H 'accept: */*' \-H 'Authorization: 6H1mlA91zFRa5yEpIl2b2mnCjbG5B44f'

删除后再打开

<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>2023-09-12/d1b5389a465f4bf7985844916d785c06.png</Key><BucketName>mingyue</BucketName><Resource>/mingyue/2023-09-12/d1b5389a465f4bf7985844916d785c06.png</Resource><RequestId>17841B7B6B41C214</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId>
</Error>

下载文件

逻辑实现

@Override
public void download(Long ossId, HttpServletResponse response) throws IOException {SysOss sysOss = this.getById(ossId);if (ObjectUtil.isNull(sysOss)) {throw new ServiceException("文件数据不存在!");}FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");OssClient storage = OssFactory.instance(sysOss.getService());try (InputStream inputStream = storage.getObjectContent(sysOss.getFileUrl())) {int available = inputStream.available();IoUtil.copy(inputStream, response.getOutputStream(), available);response.setContentLength(available);}catch (Exception e) {throw new ServiceException(e.getMessage());}
}

下载接口

@GetMapping("/download/{ossId}")
@Operation(summary = "下载OSS对象存储",parameters = { @Parameter(in = ParameterIn.PATH, name = "ossIds", description = "oss对象Ids", required = true) })
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {sysOssService.download(ossId, response);
}

下载测试

curl -X 'GET' \'http://mingyue-gateway:9100/oss/sysOss/download/1701492631160229889' \-H 'accept: */*'

image-20230912190918686

小结

文件服务基础已经完成啦,接下来可以自己尝试集成其他厂商的 OSS 服务。

文件服务更新暂告一段落,接下来弄一弄搜索服务,打算用 ES(Elasticsearch)作为搜索服务基础工具,期待一下吧~~

相关文章:

026-从零搭建微服务-文件服务(二)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…...

Jenkins 页面部分显示Http状态403 被禁止

前言 生产环境Jenkins部署了一段时间了&#xff0c;结果今天在流水线配置中&#xff0c;部分页面显示Jenkins 页面部分显示Http状态403 被禁止&#xff0c;修改配置点击保存之后偶尔也会出现这个。 问题 以下是问题图片 解决 在全局安全配置里面&#xff0c;勾选上启用代…...

ajax day4

1、promise链式调用 /*** 目标&#xff1a;把回调函数嵌套代码&#xff0c;改成Promise链式调用结构* 需求&#xff1a;获取默认第一个省&#xff0c;第一个市&#xff0c;第一个地区并展示在下拉菜单中*/let pname axios({url: http://hmajax.itheima.net/api/province,}).t…...

8.Spring EL与ExpressionParser

Spring EL与ExpressionParser 文章目录 Spring EL与ExpressionParser介绍**使用SpEL来计算评估文字字符串表达式**使用SpEL来计算评估 bean 属性 – “item.name” 介绍 Spring表达式语言(SpEL)支持多种功能&#xff0c;并且可以测试这个特殊的“ExpressionParser”接口的表达…...

Go和Java实现迭代器模式

Go和Java实现迭代器模式 1、迭代器模式 迭代器模式是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素&#xff0c;不需要知道 集合对象的底层表示。 迭代器模式属于行为型模式。 意图&#xff1a;提供一种方法顺序访问一个聚合对象中各个…...

如何在 Vue.js 和 Nuxt.js 之间做出选择?

开篇 今天看了一位国外大佬的文章&#xff0c;主要是他对在项目中如何选择 Vue.js 或 Nuxt.js 的看法&#xff0c;欢迎大家在评论区发表看法&#xff0c;以下内容是他关于这个问题看法的整理&#xff0c;由于翻译水平有限&#xff0c;欢迎大家指正。 国外大佬的看法 Vue.js在开…...

(二十三)大数据实战——Flume数据采集之采集数据聚合案例实战

前言 本节内容我们主要介绍一下Flume数据采集过程中&#xff0c;如何把多个数据采集点的数据聚合到一个地方供分析使用。我们使用hadoop101服务器采集nc数据&#xff0c;hadoop102采集文件数据&#xff0c;将hadoop101和hadoop102服务器采集的数据聚合到hadoop103服务器输出到…...

Linux: network: dhcp: mtu 这个里面也有关于网卡的MTU设置;

https://linux.die.net/man/5/dhcp-options 需注意这个DHCP配置选项。 option interface-mtu uint16; This option specifies the MTU to use on this interface. The minimum legal value for the MTU is 68. 假如在网卡的配置文件中设置了dhcp获取IP信息&#xff0c;可能导…...

Android中使用图片水印,并且能够在线下载字体并应用于水印

Android中使用图片水印&#xff0c;并且能够在线下载字体并应用于水印 要在Android中使用图片水印&#xff0c;并且能够在线下载字体并应用于水印&#xff0c;可以按照以下步骤进行&#xff1a; 1.使用Picasso、Glide或其他图片加载库加载图片&#xff1a; ImageView imageV…...

HTTP文件服务

在工作中&#xff0c;往往会需要将文件同时共享给很多台电脑。 本篇介绍HHDESK的HTTP文件服务功能&#xff0c;通过浏览器&#xff0c;将本地资源共享给任意主机。 1 共享文件 首页——资源管理——服务端——“”&#xff0c;在弹出框中选择HTTP文件服务。 填写各项内容。…...

nginx配置获取客户端的真实ip

场景描述&#xff1a; 访问路径&#xff1a; A机器 - > B机器的 ->C虚拟机 &#xff1a; A机器为客户端用户&#xff0c;本地地址为 192.168.0.110 B机器为服务端反向代理服务器 本地地址为192.168.0.128 –>&#xff08;192.168.56.1&#xff09; C机器为B主机安…...

1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据

1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据 1、时间&#xff1a;1990-2022年&#xff08;统计截止日期为 2022年7月&#xff09; 2、指标&#xff1a;证券代码、统计截止日期、姓名、国籍、籍贯、籍贯所在地区代码、出生地、出生地所在地区代码、性别…...

Java程序连接 Mysql 超时问题 - 数据包过大,导致超时,# 配置网络超时时间 socketTimeout: 1800000

问题 Java程序连接 Mysql 超时问题 解决方法 如果存在 yml 等类似的配置文件&#xff0c;那么可以配置一下 socket 连接超时的参数&#xff0c;例如 # 配置网络超时时间 半小时&#xff0c;计算公式 60秒*1000毫秒*30分钟 socketTimeout: 1800000...

c++分层最短路(洛谷飞行路线)acwing版

分层最短路算法是在SPFA算法的基础上&#xff0c;将每个点分成若干层&#xff0c;从而使得每个点之间的转移只在同一层次或上下两个相邻层次之间进行&#xff0c;减少了每轮的迭代次数&#xff0c;优化了算法的效率。 #include <iostream> #include <cstdio> #inc…...

Python bs4 BeautifulSoup库使用记录

目录 介绍 安装 初始化 解析器 使用方法 优势 Python标准库 lxml HTML lxml XML html5lib 格式化输出 对象 tag Name 多值属性 其他方法 NavigableString BeautifulSoup Comment 遍历 子节点 父节点 兄弟节点 回退和前进 搜索 过滤器 字符串 正则表达…...

Jmeter系列-插件安装(5)

前言 jmeter4.0以上&#xff0c;如现在最新的5.2.1版本是有集成插件的只需要在官网下载 plugins-manager.jar 包&#xff0c;放在jmeter安装路径的lib/ext目录下即可使用&#xff1a;https://jmeter-plugins.org/install/Install/但并不能满足所有需求&#xff0c;仍然需要安装…...

spring aop源码解析

spring知识回顾 spring的两个重要功能&#xff1a;IOC、AOP&#xff0c;在ioc容器的初始化过程中&#xff0c;会触发2种处理器的调用&#xff0c; 前置处理器(BeanFactoryPostProcessor)后置处理器(BeanPostProcessor)。 前置处理器的调用时机是在容器基本创建完成时&#xff…...

使用Unity的Input.GetAxis(““)控制物体移动、旋转

使用Unity的Input.GetAxis("")控制物体移动、旋转 Input.GetAxis("") 是 Unity 引擎中的一个方法&#xff0c;用于获取游戏玩家在键盘或游戏手柄上输入的某个轴&#xff08;Axis&#xff09;的值。这里的 "" 是一个字符串参数&#xff0c;表示要…...

【CSS】画个三角形或圆形或环

首先通过调整边框&#xff0c;我们可以发现一些端倪 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><style>.box{width: 150px;height:150px;border: 50px solid black;}</style&g…...

AI项目六:基于YOLOV5的CPU版本部署openvino

若该文为原创文章&#xff0c;转载请注明原文出处。 一、CPU版本DEMO测试 1、创建一个新的虚拟环境 conda create -n course_torch_openvino python3.8 2、激活环境 conda activate course_torch_openvino 3、安装pytorch cpu版本 pip install torch torchvision torchau…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...