轻量级 S3 协议存储客户端

news2025/4/7 1:25:54

目前大家一般不会把二进制文件直接放在应用服务器上,而是存在“对象存储”的方案中,例如亚马逊的 AWS,阿里云的 OSS、Cloudflare R2 等。AWS 为最早的始作俑者,因此其 S3 协议也近乎标准化,各大厂商的对象存储方案都实现该协议。基本上各家都有提供方便的 SDK 可以用快速调用 S3 服务,而其中的原理就难度来说并不是太复杂,笔者一时“手痒”就想打造自己的 S3 客户端。该组件主打的就是一个轻量级,不超过十个类,基本覆盖日常 OSS 的操作。

当前该组件支持 S3 协议中以下的操作:

  • 列出桶 listBucket
  • 创建、删除桶 createBucket/deleteBucket
  • 上传文件、获取文件、删除文件 putObject/getObject/deleteObject

其他比较少用到的操作,暂且不实现了。

当前支持的厂商:阿里云 OSS、网易云 NOS、Cloudflare R2,其中 Cloudflare R2 是基于 SigV4 协议的。

安装

该组件源码在:https://gitee.com/sp42_admin/ajaxjs/tree/master/aj-backend/aj-playground/aj-s3client。

Maven 坐标:

<dependency>
    <groupId>com.ajaxjs</groupId>
    <artifactId>aj-s3client</artifactId>
    <version>1.0</version>
</dependency>

使用方法

第一步是设置好 OSS 各项参数,详见配置对象 Config

/**
 * 配置
 */
@Data
public class Config {
    /**
     * 访问 API
     */
    private String endPoint;

    /**
     * 访问 Key
     */
    private String accessKey;

    /**
     * 访问密钥
     */
    private String secretKey;

    /**
     * 存储桶名称
     */
    private String bucketName;

    /**
     * 签名中的标识,每个厂商不同
     */
    private String remark;
}

这个 POJO 你通过 Spring 注入到各个厂商实现就可以了。如果不用 Spring,最简单的就是这样子的:

在这里插入图片描述
OSS 各种调用 API,详见接口S3Client,一般懂 Java 的朋友都会,就不详细介绍了。

package com.ajaxjs.s3client;

import java.util.Map;

/**
 * S3 客户端
 */
public interface S3Client {
    /**
     * 列出存储桶中的所有对象
     *
     * @return XML List
     */
    String listBucket();

    /**
     * 列出存储桶中的所有对象
     *
     * @return XML List Map
     */
    Map<String, String> listBucketXml();

    /**
     * 创建一个存储桶(Bucket)
     *
     * @param bucketName 存储桶的名称,必须全局唯一
     * @return true=操作成功
     */
    boolean createBucket(String bucketName);

    /**
     * 删除一个存储桶(Bucket)
     *
     * @param bucketName 存储桶的名称
     * @return true=操作成功
     */
    boolean deleteBucket(String bucketName);

    /**
     * 将字节数据上传到指定的存储桶中
     *
     * @param bucketName 存储桶的名称
     * @param objectName 对象(文件)在存储桶中的名称
     * @param fileBytes  要上传的文件的字节数据
     * @return true=操作成功
     */
    boolean putObject(String bucketName, String objectName, byte[] fileBytes);

    /**
     * 将字节数据上传到指定的存储桶中
     *
     * @param objectName 对象(文件)在存储桶中的名称
     * @param fileBytes  要上传的文件的字节数据
     * @return true=操作成功
     */
    boolean putObject(String objectName, byte[] fileBytes);

    /**
     * 将字节数据上传到指定的存储桶中
     *
     * @param bucketName 存储桶的名称
     * @param objectName 对象(文件)在存储桶中的名称
     * @return true=操作成功
     */
    boolean getObject(String bucketName, String objectName);

    /**
     * 将字节数据上传到指定的存储桶中
     *
     * @param objectName 对象(文件)在存储桶中的名称
     * @return true=操作成功
     */
    boolean getObject(String objectName);

    /**
     * 删除指定的文件
     *
     * @param bucketName 存储桶的名称
     * @param objectName 要删除的文件名称
     * @return true=操作成功
     */
    boolean deleteObject(String bucketName, String objectName);

    /**
     * 删除指定的文件
     *
     * @param objectName 要删除的文件名称
     * @return true=操作成功
     */
    boolean deleteObject(String objectName);
}

单元测试的配置文件application.yml没有随着 VCS 提交,其内容如下:

S3Storage:
  Nso:
    accessKey: xx
    accessSecret: xx
    api: nos-eastchina1.126.net
    bucket: xx
  Oss:
    accessKeyId: xx
    secretAccessKey: xx
    endpoint: oss-cn-beijing.aliyuncs.com
    bucket: xx
  LocalStorage: # 本地保存
    absoluteSavePath: c:\temp\ # 若有此值,保存这个绝对路径上

开发感受

这类客户端的实现过程中,感受如下几点:

  1. 仍离不开 HTTP 通讯。所谓 OSS,本质围绕着文件服务进行:文件上传、文件删除、文件下载,比较特殊一点的就是“存储桶 Bucket”的概念,这一切与服务器之间沟通仍然通过 HTTP API 进行,故所以这客户端要封装好 HttpClient 这样子组件并进行 API 通讯的调用。Cloudflare R2 官方提供 Postman 直接示例,对于我再现 Java HTTP 请求很方便
  2. 既然是协议的通讯,如何身份认证是个问题。S3 协议认证方式是每次的 HTTP 请求头加入Authorization 字段,如何生成这个合法的签名值是相对复杂的过程,包括各种参数设定和加密,占了代码很大的篇幅。S3 签名有两个版本 SigV2、SigV4,本组件都支持。
  3. 虽然同为 S3 协议,但各厂商实现的产品均有不同程度上的出入,于是在代码设计上采用子类继承了来实现这种关系:BaseS3Client–>BaseS3ClientSigV2/BaseS3ClientSigV4–>各个厂商的实现
  4. 实现过程感觉最困难的是签名生成,稍有不慎,生成的签名不合法则出现校验不通过的情况。SigV2 签名的生成方式还是比较简单的,类似阿里云文档里面的介绍:在这里插入图片描述但是 SigV4 则复杂得多,于是我找了一个很好开源实现 aws-v4-signer-java,零依赖,我简化了不少代码并将其重构了。另外,阿里云的文档也介绍得很清楚,详见这里和源码。
  5. 单元测试依然很重要,尤其写组件的时候,或者重构的时候,很多时候要把问题复现出来,单测必不可少,也能提高开发的效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1593591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苹果全力升级:用专注AI的M4芯片彻底改造Mac系列

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

vue3+elment复杂详情页面打开后,再打开其他页面都显示空白,控制台也没什么特殊报错

页面使用了el-tabs 、 el-tab-pane、el-table 等标签 但是经测试不是这些问题导致的 js也使用了onMounted &#xff0c;但是除掉也时空白页面 反正之前人写的页面可乱&#xff0c;尤其是js这块&#xff0c;穿插引用import一大堆 主题页面样式布局如下 最后看到页面代码太乱…

funasr 麦克风实时流语音识别;模拟vad检测单独输出完整每句话

参考: https://github.com/alibaba-damo-academy/FunASR chunk_size 是用于流式传输延迟的配置。[0,10,5] 表示实时显示的粒度为 1060=600 毫秒,并且预测的向前信息为 560=300 毫秒。每个推理输入为 600 毫秒(采样点为 16000*0.6=960),输出为相应的文本。对于最后一个语音…

【树莓派初始化】教你从0开始搭建树莓派的使用环境

文章目录 前言1.什么是树莓派&#xff1f;1.1什么用户适合购买树莓派学习编程&#xff1f; 2.如何初始化一个树莓派2.1 烧录系统2.2 测试开机2.3 设置树莓派显示输出的分辨率2.4 网络链接2.5 Putty链接树莓派2.6 VNC链接树莓派2.7 使用filezilla软件传输文件到树莓派 3.使用Xsh…

从 0 搭建公司Jenkins服务 Centos7

从 0 搭建公司Jenkins服务 Centos7 安装 (运维人员) 安装环境 配置DNS安装JDK17安装Jenkins安装Docker安装GIT安装Ansible启动Jenkins安装插件配置凭据配置共享库配置 (开发经理)使用 (开发、测试人员) 安装 (运维人员) 安装环境 配置DNS 新安装系统的服务器无法解析域名&a…

【数据结构】二叉爆炸

【数据结构】二叉爆炸 按照惯例整点抽象的&#xff0c;贴上这篇博客的名字由来&#xff1a; 言归正传&#xff0c;本篇博客介绍二叉树的构造方式、前中后序遍历、层序遍历以及代码随想录中二叉树章节的相关题目&#xff1a; 代码随想录 (programmercarl.com) 一、啥是二叉树 …

【150套】基于SSM框架的Java毕业设计开发实战项目(附源码+演示视频+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的Java毕业设计&#xff0c;基于ssm框架&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设计和课程…

服务器docker应用一览

文章目录 一、需求概况二、业务流程三、运行效果四、实现过程1. 基础前提2. 源码放送3.核心代码4. 项目打包5.部署步骤 一、需求概况 现有某云主机服务器&#xff0c;用来做项目演示用&#xff0c;上面运行了docker应用&#xff0c;现希望有一总览页面&#xff0c;用来展示部署…

fastjson 序列化问题

问题: 使用fastjson 的 对同一个JSONObject对象 多次引用后, 通过 JSON.toJSONString() 方法进行json序列化时出现只有第一次的可以成功序列化未json string 字符串, 后面的对象都为引用地址; 示例: public static void main(String[] args) {JSONObject jsonObject new JSON…

【C语言__结构体__复习篇3】

目录 前言 一、结构体基础知识 1.1 结构体的语法形式 1.2 创建结构体变量 1.3 结构体变量的初始化 1.4 点(.)操作符和箭头(->)操作符 二、匿名结构体 三、结构体自引用 四、结构体内存对齐 4.1 内存对齐的规则 4.2 出现结构体内存对齐的原因 4.3 修改默认对齐数 五、结…

【YOLOv9】完胜V8的SOTA模型Yolov9(论文阅读笔记)

官方论文地址&#xff1a; 论文地址点击即可跳转 官方代码地址&#xff1a; GitCode - 开发者的代码家园 官方代码地址点击即可跳转 1 总述 当输入数据经过各层的特征提取和变换的时候&#xff0c;都会丢失一定的信息。针对这一问题&#xff1a; 论文中提出的可编程梯度信息…

高颜值的B端界面,如果漂亮也有错,就让它错下去吧。

分享一波漂亮的B端界面&#xff0c;内行看门道&#xff0c;外行看热闹&#xff0c;不喜勿喷昂。

防止狗上沙发,写一个浏览器实时识别目标检测功能

家里有一条狗&#x1f436;&#xff0c;很喜欢乘人不备睡沙发&#x1f6cb;️&#xff0c;恰好最近刚搬家 狗迎来了掉毛期 不想让沙发上很多毛。所以希望能识别到狗&#xff0c;然后播放“gun 下去”的音频&#x1f4e3;。 需求分析 需要一个摄像头&#x1f4f7; 利用 chrome…

反激电源RC吸收电路设计

一、什么是RC吸收&#xff1f; RC吸收是指在电路设计中&#xff0c;尤其是在开关电源、功率电子设备以及电力电子系统中&#xff0c;使用电阻与电容串联组成的电路结构&#xff0c;用于吸收和衰减电路中由于开关元件&#xff08;如MOSFET、IGBT等&#xff09;的快速切换所产生的…

Blender2.83 下载地址及安装教程

Blender是一款开源的3D计算机图形软件&#xff0c;广泛应用于动画制作、游戏开发、建模、渲染等领域。它提供了一套强大的工具和功能&#xff0c;让用户能够进行三维建模、动画制作和视觉效果的创作。 Blender支持多种文件格式的导入和导出&#xff0c;使用户能够与其他软件进…

从汇编指令看函数调用堆栈的详细过程

我们以下述代码为例来说明函数调用堆栈的详细过程 #include<iostream>int sum(int a,int b) {int temp0;tempab;return temp; }int main() {int a10;int b20;int retsum(a,b);std::cout<<"ret:"<<ret<<std::endl;return 0; } 接下来&#…

粒子群优化算法PSO与鹈鹕优化算法(POA)求解无人机三维路径规划(MATLAB代码)

一、无人机路径规划模型介绍 二、算法介绍 close all clear clc dbstop if all error warning (off) global model model CreateModel(); % 创建模型 FF1; [Xmin,Xmax,dim,fobj] fun_info(F);%获取函数信息 pop100;%种群大小(可以自己修改) maxgen100;%最大迭代次数(可以自己…

电商数据采集的网页抓取数据、淘宝、天猫、京东等平台的电商数据抓取|电商数据API接口网页爬虫、采集网站数据

电商数据采集的网页抓取数据、淘宝、天猫、京东等平台的电商数据抓取&#xff0c;网页爬虫、采集网站数据、网页数据采集软件、python爬虫、HTM网页提取、APP数据抓包、APP数据采集、一站式网站采集技术、BI数据的数据分析、数据标注等成为大数据发展中的热门技术关键词。那么电…

以太网数据量大小字符串生成方法(可变单位)

0 前言 当我们想显示以太网数据量大小时&#xff0c;往往有个头疼的单位需要处理&#xff0c;单位取小了不一目了然&#xff0c;单位取大了精度太低。本例设计一个函数&#xff0c;将根据以太网数据量大小自动生成单位可变的字符串&#xff08;KB、MB、GB、TB、PB&#xff09;…

CSS之固定定位、相对定位、绝对定位

一、相对定位 相对元素自身所在的原来的位置进行定位&#xff0c;可以设置 left&#xff0c;right&#xff0c;top&#xff0c;bottom四个属性。 效果&#xff1a;在进行相对定位以后&#xff0c;元素原来所在的位置被保留了&#xff0c;既保留占位&#xff0c;其他元素的位置…