近期公司文件服务器用了青云QingStor的对象存储,协议用的是AmazonS3协议,
青云对象存储的使用手册在这里 https://docs.qingcloud.com/qingstor/s3/
其中介绍了api和sdk但是sdk并不是对s3协议的,所以我原本使用sdk后,一直返回的是401,access_id不存在,也就是官网中的错误码的第一条
后期才发现原来我们用的是s3协议,有点小尴尬
我使用的s3协议代码如下
一、引入jar包 jar有些大
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-sdk-java</artifactId>
<version>2.5.59</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.567</version>
</dependency>
二、创建AmazonS3连接
AmazonS3连接这里采用的是单例,但是是传参进来的,因为授权id都在配置文件中,所以static中我用的是传参方式
用到的参数主要有
* @param accessKeyId s3 accessKeyId
* @param secretAccessKeyId s3 secretAccessKey
* @param zone 上传对象存储的磁盘区域
* @param bucketName bucket名称
* @param url 上传的对象存储服务器路径
其中 accessKeyId 和secretAccessKey 和像是auth2授权的那种感觉
AmazonS3Client
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
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;
/**
* AWS s3协议创建对象
* @ClassName: AmazonS3Client
* @author lxn
* @date 2019年6月10日 下午5:51:07
*/
public class AmazonS3Client {
private static volatile AmazonS3 s3Client;
private AmazonS3Client() {}
/**
*
* 获取s3连接
* @param accessKeyId s3 accessKeyId
* @param secretAccessKeyId s3 secretAccessKey
* @param zone 上传对象存储的磁盘区域
* @param bucketName bucket名称
* @param url 上传的对象存储服务器路径
* @return s3连接
* @author lxn
* @Time 2019年6月10日 下午6:31:10
*/
public static AmazonS3 getInstance(String accessKeyId, String secretAccessKeyId, String zone, String bucketName, String url) {
if (s3Client == null) {
synchronized (AmazonS3Client.class) {
if (s3Client == null) {
//创建Amazon S3对象使用明确凭证
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKeyId);
ClientConfiguration clientConfig = new ClientConfiguration();
clientConfig.setSignerOverride("S3SignerType");//凭证验证方式
clientConfig.setProtocol(Protocol.HTTP);//访问协议
s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withClientConfiguration(clientConfig)
.withEndpointConfiguration(
/**
* 设置要用于请求的端点配置(服务端点和签名区域)
* url s3服务器地址
* zone 存储的区域(青云目前是 北京和上线)
*/
new AwsClientBuilder.EndpointConfiguration(url,zone))
.withPathStyleAccessEnabled(true)//是否使用路径方式,是的话s3.xxx.sn/bucketname
.build();
}
}
}
return s3Client;
}
}
zone青云的地址码
image.png
三、文件的上传
//青云accessKeyId
@Value("${qingStor.qy_access_key_id}")
private String accessKeyId;
//青云qy_secret_access_key
@Value("${qingStor.qy_secret_access_key}")
private String secretAccessKeyId;
//bucketname
@Value("${qingStor.bucket}")
private String bucketName;
//上传区域
@Value("${qingStor.zone}")
private String zone;
//上传云地址
@Value("${qingStor.url}")
private String url;
/**
* 获取s3连接
*/
AmazonS3 s3Client = AmazonS3Client.getInstance(accessKeyId, secretAccessKeyId, zone, bucketName, url);
/**
* 对象上传
*/
logger.info("{}调用青云对象存储上传:", LogUtils.getApplicationInfo(objectName, loginUserId));
PutObjectResult result = s3Client.putObject(bucketName, objectName, file);
如果result返回的参数中md5值不为空则上传成功
result.getContentMd5()
其中的objectName对青云来说是文件的唯一标志,如果不同的文件的objectname相同,则后上传的文件会覆盖之前上传的文件
image.png
四、文件下载
public void down() {
try {
AmazonS3 s3Client = AmazonS3Client.getInstance(accessKeyId, secretAccessKeyId, zone, bucketName, url);
S3Object o = s3Client.getObject(bucketName, objectName);
S3ObjectInputStream s3is = o.getObjectContent();
FileOutputStream fos = new FileOutputStream(new File("D:\\test\\bt.jpg"));
byte[] read_buf = new byte[1024];
int read_len = 0;
while ((read_len = s3is.read(read_buf)) > 0) {
fos.write(read_buf, 0, read_len);
}
s3is.close();
fos.close();
} catch (AmazonServiceException e) {
System.err.println(e.getErrorMessage());
System.exit(1);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
效果如下
image.png
好啦,大家可以一起试试哈,其实对于单例那个地方我觉得还可以优化
网友评论