背景
项目中使用了oss存储服务, 各大厂商有自己的sdk, 并且sdk引用了其它的sdk,安全扫描时发现包需要升级,升级完了一团浆糊,大家既然都遵循AWS3的行业协议我为啥不使用AWS3的行业协议来对接呢?
完整版测试用代码
maven导包:
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.12.739</version> </dependency>
完整版代码:
java
package com.easy.nosql;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.CreateBucketRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AWSS3ClientDemo {
public AmazonS3 s3;
public String region = "";
public void init(String endpoint, String accessKey, String secretKey,String region) {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
this.region = region;
this.s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration(endpoint, region)
)
// 关键 2:开启 PathStyle 模式(华为云 OBS 必须开启)
// .withPathStyleAccessEnabled(false)
// .withChunkedEncodingDisabled(false)
.build();
}
public static void main(String[] args) throws Exception {
AWSS3ClientDemo s3 = new AWSS3ClientDemo();
// 替换自己的endpoint/accessKey/secretKey/region等关键信息
s3.init("http://127.0.0.1:9000",
"admin", "admin123456",
"easy");
String bucketName = "easy";
// 桶是否存在
boolean flag = s3.doesBucketExist(bucketName);
System.err.println(flag);
// 创建桶
if (!flag) {
// 创建新的桶
s3.createBucket(bucketName);
}
// 再次查找桶是否存在
System.out.println(s3.doesBucketExist(bucketName));
if(1!=1){
return;
}
// 上传文件
s3.upload(bucketName, "test001.txt", new ByteArrayInputStream("这是我的菜".getBytes()));
// 下载文件
byte[] easy001s = s3.down(bucketName, "test001.txt");
// 查看文件内容
System.err.println(new String(easy001s));
// 查看文件长度。
System.err.println(s3.getContentLength(bucketName, "test001.txt"));
// 睡眠20秒, 这个时候去控制台查看对应的文件是否创建,
TimeUnit.SECONDS.sleep(20);
// 删除文件
System.err.println(s3.delete(bucketName, "test001.txt"));
// 再次判断文件是否存在
System.err.println(s3.doesFileExist(bucketName, "test001.txt"));
}
public List<Bucket> listBuckets(){
return s3.listBuckets();
}
public boolean doesBucketExist(String bucketName) throws Exception {
return s3.doesBucketExist(bucketName);
}
public void createBucket(String bucketName) throws Exception {
// 华为云的桶创建,必须增加region区域字段。
s3.createBucket(new CreateBucketRequest(bucketName, region));
}
public void upload(String bucketName, String path, InputStream file) throws Exception {
s3.putObject(bucketName, path, file, null);
}
public byte[] down(String bucketName, String path) throws Exception {
try (S3Object object = s3.getObject(bucketName, path)) {
if (object.getObjectContent() == null) {
throw new RuntimeException("inputStream should not be null");
}
return IoUtil.readToByteArray(object.getObjectContent());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public boolean delete(String bucketName, String path) throws Exception {
try {
s3.deleteObject(bucketName, path);
return Boolean.TRUE;
} catch (Exception e) {
e.printStackTrace();
}
return Boolean.FALSE;
}
public boolean doesFileExist(String bucketName, String path) throws Exception {
return s3.doesObjectExist(bucketName, path);
}
public Long getContentLength(String bucketName, String path) throws Exception {
ObjectMetadata metadata = s3.getObjectMetadata(bucketName, path);
return metadata.getContentLength();
}
private static final List<Pattern> REGION_PATTERN_LIST =
Arrays.asList(
// cos=腾讯云
Pattern.compile("cos\\.([a-z0-9-]+)\\.myqcloud"),
// obs=华为云
Pattern.compile("obs\\.([a-z0-9-]+)\\.myhuaweicloud"),
// oss=阿里云
Pattern.compile("oss-([a-z0-9-]+)\\.aliyuncs"),
// bcebos=百度云
Pattern.compile("s3\\.([a-z0-9-]+)\\.bcebos.com")
);
/**
* 不方便用户手动录入时,可以通过正则来获取region信息。
*
* @param endpoint 请求地址
* @return
*/
public String getRegion(String endpoint) {
if (endpoint == null || endpoint.isEmpty()) {
return "";
}
for (Pattern pattern : REGION_PATTERN_LIST) {
Matcher matcher = pattern.matcher(endpoint);
// 查找是否存在匹配项,存在则返回第一个捕获组(区域标识)
if (matcher.find()) {
return matcher.group(1);
}
}
return ""; // 匹配失败(如 URL 格式错误)
}
}
华为云对接(OBS)
首先获取ak/sk

创建自己的桶,桶名称全局不能重复(其它用户创建了我们也不能用了)

编码:
java
BasicAWSCredentials credentials = new BasicAWSCredentials("key", "value");
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration("obs.cn-north-4.myhuaweicloud.com", "cn-north-4")
)
// 关键 2:开启 PathStyle 模式(华为云 OBS 必须开启)
.withPathStyleAccessEnabled(true)
.withChunkedEncodingDisabled(true)
.build();
创建桶报错:The location constraint is incompatible for the region specific endpoint this request was sent to. 
华为云存储, 要求创建桶时必须设置区域:
bos.createBucket(new CreateBucketRequest(bucketName,"cn-north-4"));
其它判断桶是否存在,上传文件,下载文件,文件大小查看,查看前几行文件等功能正常。
验证完了记得清空桶及桶内的文件,防止文件存储产生的费用
百度云对接(BOS)
密钥对获取

服务开通:

官方推荐的编码:https://cloud.baidu.com/doc/BOS/s/ojwvyq973#aws-sdk-for-java

验证完了记得清空桶及桶内的文件,防止文件存储产生的费用
阿里云对接(OSS)
密钥对获取

服务开通:

桶删除:

腾讯云对接(COS)

代码:
BasicAWSCredentials credentials = new BasicAWSCredentials("KEY", "Value");
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration("cos.ap-guangzhou.myqcloud.com", "ap-guangzhou")
)
// 关键 2:开启 PathStyle 模式(华为云 OBS 必须开启)
.withPathStyleAccessEnabled(false)
.withChunkedEncodingDisabled(false)
.build();
报错: Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request; Request ID: xxx; Proxy: null), S3 Extended Request ID: null
原因: 腾讯云要求桶的名称必须以-appId结尾,就是上图我们看到的appId,
七牛云对接(KODO)
获取密钥:

minio对接(本地部署)
accessKey: 账号
secretKey:密码
region: 随便输入,不强制要求
minio是本地部署的,所以没有密钥创建等一系列复杂处理。直接输入端点和账号密码即可,
亚马逊云对接(s3)
账号申请需要准备信用卡等信息。
示例端点:s3.ap-northeast-1.amazonaws.com
密钥创建:

桶删除:
