
简介esdk-obs-java-3.20.3.zip 是华为云对象存储服务OBS的 Java SDK 资源包面向需要在 Java 应用中实现上传、下载、桶管理等云存储操作的开发者也适合正在评估或维护 OBS 对接方案的技术人员既能让初学者借助示例快速上手也能供有经验的工程师按需查阅 API 细节。压缩包内共含 766 个文件整体大小约 7.31MB其中 449 个 HTML 文件构成完整的 Javadoc API 文档286 个 Java 文件提供示例代码与源码另有 XML 配置、JAR 依赖、Markdown 说明和构建脚本可满足查阅、调试、二次开发等多种需要。目前已有 1813 人浏览学习是较受关注的 OBS SDK 配套资源。通过 ObsClient、IObsClient、SecretFlexibleObsClient 等核心类文档及示例工程开发者可以快速掌握客户端初始化、对象上传下载、桶的列举与删除等关键操作结合 log4j2 日志配置、pom.xml 依赖和构建脚本还能在真实项目中减少环境配置与排错难度提升云存储接入效率。包内对 ObsException、HeaderResponse 等异常与响应信息也有明确说明可帮助开发者少走弯路。1. 先搞清楚esdk-obs-java到底是什么很多刚接触云存储的Java开发拿到esdk-obs-java-3.20.3.zip这个压缩包时第一反应是这又是哪个私有SDK。其实它一点都不神秘这是华为云对象存储服务 OBS 的 Java 语言开发套件eSDK 是华为企业软件开发套件的统称OBS 是 Object Storage Service 的缩写合在一起就是让 Java 程序操作 OBS 的一整套 API 封装。3.20.3 是版本号表示 3.x 大版本下比较新的稳定补丁版。这个包能解决什么问题简单说就是让 Java 后端代码像操作本地磁盘一样操作云上的对象存储上传文件、下载文件、删除对象、生成临时访问链接、设置生命周期规则等。适合做日志归档、用户上传文件存储、大数据离线分析、备份容灾这类业务。如果你的项目遇到本地磁盘不够用、多机共享文件困难、文件需要长期冷备用它就对了。但前提是你得先搞清楚它和另一个网上经常出现的 OBS 不是同一个东西。1.1 从文件名拆解esdk、obs、java各代表什么我们先拆名字。esdk 全称 Enterprise Software Development Kit华为很多云服务的 SDK 都以 eSDK 开头代表面向企业开发者的标准开发套件。obs 是 Object Storage Service对象存储服务可以把它理解成一个无限容量、按量付费的网盘但对外提供的是 HTTP/HTTPS 接口而不是图形界面。java 表示这套 SDK 是用 Java 写的提供了丰富的 API封装了签名、重试、连接池等底层逻辑。3.20.3 这个版本号也值得看。3 是大版本说明它已经承载了 3.x 时代的功能20.3 一般表示 2020 年 3 月前后发布的迭代但因为云服务 SDK 更新频繁后续的 3.20.x 系列都是在持续修复问题和增加新功能所以拿到 3.20.3 可以认为是一个已经打磨得比较稳的版本。相比 2.x3.x 的 API 命名更统一对 JDK8 及以上版本支持更友好同时补齐了临时凭证、生命周期管理等高频能力。1.2 OBS的两幅面孔对象存储与直播录屏软件别搞混这里必须多提醒一句。现在搜索 OBS 跳出来的很大概率是 OBS Studio也就是 Open Broadcaster Software一个开源的录屏和直播推流工具。很多人在搜obs录屏卡顿obs背景移除obs下载 百度网盘他们找的是那个用来在抖音、B站双平台直播游戏的软件。这和本文要讲的对象存储服务完全不是一回事。如果你是一个主播看到标题里有 obs 以为是 OBS Studio 的插件压缩包下载回来发现是 Java SDK大概率会一脸懵。反过来如果你是 Java 开发想用云存储功能别去下载 OBS Studio。记住华为云 OBS 的对象存储服务控制台是云控制台SDK 是com.huaweicloud:esdk-obs-javaOBS Studio 是本地软件插件目录、推流地址这些词和它绑定。搞混了后面的路全部会走偏。1.3 3.20.3版本在生态中的位置3.20.3 在 OBS Java SDK 生态中属于中间偏新的稳定版本。它基于 JDK8 开发同时兼容 JDK8、JDK11、JDK17 等主流版本。相比更早的 3.x 版本它修复了一些连接池偶发泄漏、DNS 解析异常时重试不到位的问题也对对象元数据的功能做了增强。如果项目是全新的直接用最新稳定版肯定没错如果是老项目还在 2.x建议规划升级因为 3.x 的 API 更规范长期维护成本更低。我个人的经验是不要总追最新版本但要避开非常老的版本。SDK 是基础组件稳定比什么都重要。3.20.3 属于那种已经被很多生产环境验证过的版本踩坑概率低。2. 拿到压缩包之后的第一步引入依赖还是本地安装拿到esdk-obs-java-3.20.3.zip千万别急着解压往项目里塞。先想清楚依赖管理方式。因为 SDK 不仅仅是那一个 jar 文件它还有一堆第三方依赖最省心的做法还是通过 Maven 或 Gradle 引入坐标。2.1 解压结构与SDK组件一览为了讲清楚为什么不能只拿核心 jar我们先看解压后的目录结构通常是这样的esdk-obs-java-3.20.3/ ├── esdk-obs-java-3.20.3.jar ├── dependency/ │ ├── jackson-core-xxx.jar │ ├── jackson-databind-xxx.jar │ ├── okhttp-xxx.jar │ ├── slf4j-api-xxx.jar │ └── ... ├── docs/ │ ├── API参考.html │ └── 开发指南.pdf └── examples/ └── ...esdk-obs-java-3.20.3.jar是核心包但里面很多类是空的真正的 HTTP 通信、JSON 解析、日志输出都依赖dependency目录下的第三方库。如果只把这个核心 jar 复制到项目里运行起来立刻就会抛NoClassDefFoundError。这个目录结构其实就是给离线环境准备的允许你手动把依赖全部收齐但不代表你可以只挑一个 jar 用。2.2 三种引入方式Maven、Gradle、手动导入jar大部分常规项目建议用 Maven。在pom.xml里加dependency groupIdcom.huaweicloud/groupId artifactIdesdk-obs-java/artifactId version3.20.3/version /dependencyGradle 项目则用implementation com.huaweicloud:esdk-obs-java:3.20.3配置好之后Maven 或 Gradle 会自动拉取依赖不需要手动管理dependency目录。但如果你的开发环境是纯内网无法访问中央仓库那就只能把 zip 解压把核心 jar 和dependency下所有 jar 都导入 IDE或放进 Web 项目的WEB-INF/lib。手动导入的问题在于依赖是静态的后续版本升级、依赖冲突都要人工处理很容易漏。2.3 为什么推荐Maven仓库而不是直接引zip里的jar直接引 zip 里的 jar 有一个非常大的隐患依赖冲突。比如你的项目里已经用了老版本 JacksonSDK 要用新版本 Jackson运行时经常出现NoSuchMethodError。用 Maven 的好处是能自动管理依赖传递你只需要声明一个坐标它会把配套的第三方库全部拉齐还能通过依赖树统一排查冲突。如果是内网项目也可以把 SDK 安装到本地仓库让项目继续用坐标引用mvn install:install-file -Dfileesdk-obs-java-3.20.3.jar -DgroupIdcom.huaweicloud -DartifactIdesdk-obs-java -Dversion3.20.3 -Dpackagingjar但这种方式只解决了本地仓库问题如果团队多人协作最好用 Nexus 私服把 jar 传到 Hosted 仓库大家统一走内网私服拉取。别嫌麻烦这一步做对了后面会省掉很多我这个环境怎么会这样的问题。3. 初始化客户端与鉴权配置SDK 引入成功只是开始真正动手写代码前要先搞定访问凭证和 Endpoint。对象存储不像本地磁盘你想访问任何一个桶都必须先通过 AK/SK 签名认证。3.1 AK/SK与终端的正确姿势AK/SK 是云平台的访问密钥AK 是用户标识SK 是签名密钥可以理解成账号 密码。在华为云控制台 IAM 里创建一个用户然后生成一组 AK/SK下载后务必保存在安全的地方。千万别写死在代码里更别提交到 Git 仓库。我见过有人把 AK/SK 明文推到 GitHub 上几个小时后就被爬虫刷走云账户被创建了一堆高配实例账单惨不忍睹。除了 AK/SK你还需要 Endpoint。不同区域 Endpoint 不一样比如华北北京四是obs.cn-north-4.myhuaweicloud.com华南广州是obs.cn-south-1.myhuaweicloud.com。桶名是全局唯一的但 Endpoint 决定了这个桶在哪个区域创建和访问。如果你的桶在北京四就别用华南的 Endpoint 去访问否则会一直提示桶不存在。另外如果连 Java 环境变量都没配置好先停下来处理JAVA_HOME和PATH确保java -version能正常输出再往下走。3.2 创建ObsClient的几种方式基础用法就是用 AK/SK Endpoint 构造String ak System.getenv(OBS_AK); String sk System.getenv(OBS_SK); String endPoint https://obs.cn-north-4.myhuaweicloud.com; ObsClient obsClient new ObsClient(ak, sk, endPoint);如果用的是临时凭证还需要传入安全令牌ObsClient obsClient new ObsClient(ak, sk, securityToken, endPoint);临时凭证常用于委托授权、STS 场景有效期一般不会太长业务侧需要做好定期刷新。无论哪种方式有一个原则要记住ObsClient是线程安全的一个 JVM 里同一个区域维护一个客户端就够了不要每次操作都 new 一个否则连接池和线程资源都会被浪费性能急剧下降。3.3 网络与代理配置的坑在公司内网环境下经常会遇到需要通过 HTTP 代理才能访问公网的情况。这个时候不要依赖 JVM 的全局代理参数直接在ObsClient上设置更明确obsClient.getHttpClient().setProxyHost(proxy.example.com); obsClient.getHttpClient().setProxyPort(8080);我踩过的一个坑是代码里设置了 JVM 的-Dhttps.proxyHost但 SDK 内部走的是独立的 HTTP 客户端完全没理会这个参数结果一直连接超时。后来在ObsClient上显式设置代理问题立刻解决。除了代理连接超时和读取超时也要根据实际网络情况调整默认值在某些跨地域传输场景下会偏小大文件上传容易SocketTimeout可以适当调大但也不要无限调大否则故障时请求长时间挂着很难受。4. 高频业务场景实战上传、下载、断点续传初始化好客户端接下来就是最常见的业务操作。这一节我把实际项目里用的最多的几个场景写一下代码都是可以直接改改用的。4.1 文件上传简单上传与流式上传上传本地文件最简单一行代码PutObjectResult result obsClient.putObject(my-bucket, logs/2024-01-01/app.log, new File(/data/app.log));这里第一个参数是桶名第二个是对象在桶里的路径即对象键第三个是本地文件。对象键可以带/看起来像目录但对象存储本身并没有真正的目录层级这只是逻辑上的命名习惯。如果是把网络流直接转存到 OBS可以用流式上传try (InputStream in new URL(https://example.com/data.zip).openStream()) { obsClient.putObject(my-bucket, download/data.zip, in); }流式上传的好处是不用先把文件落盘但要注意流必须正确关闭否则连接池会被占满。上传时还能设置元数据比如 ContentType、ContentEncoding、用户自定义属性ObjectMetadata metadata new ObjectMetadata(); metadata.setContentType(text/plain); metadata.setContentLength(file.length()); metadata.addUserMetadata(source, daily-backup); obsClient.putObject(my-bucket, backup/app.log, new File(/data/app.log), metadata);对于几十 MB 的小文件putObject完全够用。但超过几百 MB我建议直接用下面要讲的断点续传效率高一个量级。4.2 断点续传与并发控制uploadFile是 SDK 封装好的断点续传接口底层其实是分片上传把大文件切成多个分片并行上传并且本地记录进度。中途失败后下一次可以从已上传的分片继续不用重头再来。UploadFileRequest request new UploadFileRequest(my-bucket, backup/bigdata.bin); request.setUploadFile(/data/bigdata.bin); request.setTaskNum(5); request.setEnableCheckpoint(true); request.setPartSize(5 * 1024 * 1024); // 5MB分片 obsClient.uploadFile(request);taskNum是并发分片数量不是越大越好。我实测在普通带宽下5 到 10 个并行分片就已经很稳继续加大反而会触发服务端限流。partSize默认值是 5MB如果文件特别大可以调成 10MB 到 20MB减少分片数量也能降低一部分网络开销。特别提醒小文件不要用断点续传。我见过有人对所有文件都用uploadFile结果传一个几百 KB 的配置文件也要先初始化检查点文件总耗时反而是简单上传的好几倍。所以要区分场景大文件才走分片续传。4.3 下载与对象属性获取下载对象最基础的是getObjectObsObject obsObject obsClient.getObject(my-bucket, backup/bigdata.bin); try (InputStream in obsObject.getObjectContent()) { // 处理流 }如果要直接下载到本地文件可以写成GetObjectRequest request new GetObjectRequest(my-bucket, backup/bigdata.bin); obsClient.getObject(request, new File(/local/bigdata.bin));有时候只需要文件的一部分比如视频预览只需要前 1MB可以用 Range 请求GetObjectRequest request new GetObjectRequest(my-bucket, video/demo.mp4); request.setRangeStart(0L); request.setRangeEnd(1024 * 1024L);另外一个非常常用的功能是生成临时授权 URL。比如前端要直接上传图片到 OBS但又不希望把 AK/SK 暴露出去可以让后端生成一个带签名、有效期几分钟的 URLTemporarySignatureRequest req new TemporarySignatureRequest(HttpMethodEnum.PUT, 300); req.setBucketName(my-bucket); req.setObjectKey(upload/photo.jpg); TemporarySignatureResponse res obsClient.createTemporarySignature(req); String signedUrl res.getSignedUrl();前端拿到这个 URL 后可以直接 PUT 文件过期后会自动失效既安全又省事。5. 常见问题与排查技巧实录SDK 用久了总会遇到一些奇怪的问题。我把最常见的几类整理出来都是实际项目中踩过的坑希望能帮你少走弯路。5.1 启动报错NoClassDefFoundError遇到NoClassDefFoundError十有八九是依赖缺失。比如报错信息里有com.fasterxml.jackson.core.JsonFactory就是项目里没有 Jackson或者版本不对。先用 Maven 的mvn dependency:tree查看依赖树看是否引入了多个版本的 Jackson。如果冲突可以用exclusions排除旧版本或者用dependencyManagement统一版本。还有一种情况是某个类真的被 JDK 移除了比如老代码用了java.applet.AppletJDK11 之后已经删掉了这类 API所以报NoClassDefFoundError: java/applet/Applet。这个锅不在 SDK而是你的运行环境或老代码不兼容解决办法是升级代码或者换回 JDK8。面试里背过 ClassLoader 和 ClassNotFoundException并不代表实际排障时不会懵分清这两类错误很重要。5.2 连接超时与DNS解析连接超时的原因很多。先确认 Endpoint 网络通不通用curl -I https://obs.cn-north-4.myhuaweicloud.com测一下。如果内网有防火墙需要放通 443 端口。如果报UnknownHostException优先检查 DNS 配置尤其是容器环境Pod 的 DNS 策略可能导致偶尔解析不了外网域名。我之前在一个 Kubernetes 集群里遇到 OBS 偶发连接失败排查到最后是 CoreDNS 在某些节点上不稳定换成 NodeLocal DNSCache 后问题消失。如果网络没问题但上传大文件还是超时检查 SDK 的超时设置。默认连接超时是 10 秒左右实际上不同版本可能不一样最好显式设置HttpClient httpClient new HttpClient(); httpClient.setConnectionTimeout(30000); httpClient.setSocketTimeout(30000); ObsClient obsClient new ObsClient(ak, sk, endPoint, httpClient);5.3 权限不足与签名不一致AccessDenied是权限问题的标配。第一步确认 AK/SK 是否有对应桶的权限第二步检查桶策略和 IAM 授权第三步看临时凭证是否过期。临时凭证过期是高频问题特别是用 STS 做跨账号授权时注意刷新逻辑。SignatureDoesNotMatch这种签名不一致错误最大的坑是系统时间不准。OBS 签名算法要求客户端时间与服务器时间误差在 15 分钟内我遇到过一台服务器时间慢了 10 分钟结果所有请求都签名失败执行ntpdate同步后立刻恢复。如果你用 Docker 容器宿主机关机后又开机容器内时间可能会出现偏移也要注意同步。5.4 SDK日志开启与排查技巧遇到看不懂的问题不要瞎猜先开 SDK 的 DEBUG 日志。3.x 基于 slf4j你只要在 classpath 里放一个 logback 或 log4j2 配置文件把com.obs.services的日志级别调到 DEBUG就能看到完整的请求 URL、请求头、响应状态码。日志里最关键的是x-obs-request-id。这个 ID 是这次请求在 OBS 服务端的唯一标识给华为云提工单时带上它对方能直接查服务端日志。我每次排查权限问题第一件事都是从日志里把 requestId 捞出来没有它对方也只能让你反复复现问题。6. 版本升级与性能优化建议稳定运行之后也不能一直守着老版本不升级。SDK 的版本演进往往会带来 API 调整和新能力同时性能和内存调优也值得关注。6.1 3.x版本演进带来的变化从 2.x 升级到 3.x最直观的感受是 API 更统一。旧版本里一些异步接口写得比较绕3.x 统一成同步阻塞的ObsClient理解成本低了不少。桶管理、生命周期、跨区域复制这些能力也补全了对 JDK8 的支持也更友好。3.20.3 在 3.x 里属于比较成熟的版本如果项目还在用 3.0 早期版本建议直接升到 3.20.3修复了不少连接池和重试逻辑的问题。6.2 从2.x迁移到3.x的注意事项迁移的时候不要直接全局替换。先看官方 Release Notes重点排查几个点一是构造方法的参数变化旧版可能只接受 AK/SK新版支持临时凭证和自定义鉴权 Provider二是部分类名或方法签名变化编译后会直接暴露问题三是行为变化比如旧版本某些接口默认不重试新版本会自动重试这会导致业务侧的表现略有不同。建议封装一个工具类把上传下载操作统一封装外部业务不要到处直接调 SDK这样升级时只改工具类一处影响面可控。6.3 内存与性能调优大批量上传文件时不要在 for 循环里一个个putObject性能太差。我一般用一个固定线程池并发提交核心逻辑类似这样ExecutorService pool Executors.newFixedThreadPool(10); files.forEach(f - pool.submit(() - { try { obsClient.putObject(bucket, f.getKey(), f.getFile()); } catch (Exception e) { log.error(upload failed: {}, f.getKey(), e); } }));但并发提交之后必须做好失败重试和统计我还会用一个CountDownLatch或Future等待全部完成再继续后续逻辑。并发度不要盲目拉高否则本机带宽和 OBS 服务端限流会让你得不偿失。另外ObsClient内部有连接池默认连接数可能不够高并发场景可以像 5.2 节那样自定义HttpClient参数。同时注意流式上传时一定要关闭流否则连接池会被占满最终表现为获取连接超时。我曾经排查过一个偶发不可用问题日志卡在等待连接最后定位就是循环里有人忘记关闭上传流。还有个容易被忽略的点对于日志归档这类写多读少的场景可以让对象上传后通过生命周期规则自动转成低频或者归档存储成本能省不少。不过那是控制台配置的事SDK 只负责上传你别在代码里去实现定时转储直接用云上生命周期功能更省心。最后再分享一个我自己的习惯每次升级 SDK 版本我都会先在一个模拟环境跑一遍核心上传下载流程重点看requestId是否每次都正常返回、连接池是否有异常增长。云存储 SDK 这种基础组件稳定是第一位的平时多留意版本发布记录遇到奇怪问题先看看是不是已知 bug再去怀疑自己的代码。本文还有配套的精品资源点击获取