前言
因为给某市做一个核酸预约登记扫码的防疫系统需要和联通合作,采用了联通云的对象存储技术,希望能给使用联通OSS的小伙伴们踩个坑。
一、对象存储OSS?
对象存储产品(Object Storage Service,简称 OSS),是提供的海量、安全、低成本、高可靠的云存储服务。
二、使用步骤
1.POM引入
引入亚马逊aws依赖:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.24</version>
</dependency>
2.对象上传
代码如下(示例):
// 此处的AK和SK填写自己的
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials("accessKey", "secretKey");
// 创建OSSClient实例。
AmazonS3 amazonS3 = new AmazonS3Client(basicAWSCredentials);
// 设置endpoint
amazonS3.setEndpoint("https://obs-jsnj.woyun.cn");
S3ClientOptions s3ClientOptions = S3ClientOptions.builder().setPathStyleAccess(true).setPayloadSigningEnabled(true).build();
amazonS3.setS3ClientOptions(s3ClientOptions);
// 桶名称
String bucketName = "demo";
try {
/**
* ======================= 上传 =====================================================
*/
String objectKey = "甘雨神里.jpg";
File file = new File("/Users/ddogring/Pictures/甘雨神里.jpeg");
String fileName = file.getName();
objectKey = String.format(objectKey, fileName);
// 判断桶是否存在
if (!amazonS3.doesBucketExist(bucketName)) {
// 创建桶实例(容器, 无需重复创建)
amazonS3.createBucket(bucketName);
}
// 创建对象请求
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, file);
// 也可以文件流方式上传
// InputStream is = new FileInputStream(file);
// ObjectMetadata metadata = new ObjectMetadata();
// metadata.setContentType(fileName);
// PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, is, metadata);
// 设置读写权限
putObjectRequest.withCannedAcl(CannedAccessControlList.Private);
// 提交对象
PutObjectResult result = amazonS3.putObject(putObjectRequest);
if (Objects.nonNull(result)){
System.out.println("result:=============================================================");
System.out.println("result.getContentMd5():"+result.getContentMd5());
System.out.println("result.getETag():"+result.getETag());
System.out.println("result.getMetadata():"+result.getMetadata());
System.out.println("result.getVersionId():"+result.getVersionId());
System.out.println("result.getExpirationTimeRuleId():"+result.getExpirationTimeRuleId());
System.out.println("result.getExpirationTime():"+result.getExpirationTime());
}
} catch (Exception e){
e.printStackTrace();
}
3.关于AK和SK的获取
登陆联通云,进入控制台,当时找了好久才发现,链接这么小!!!
4.关于微信小程序直传
因为我们做的是微信小程序,考虑到带宽和安全问题,不考虑服务端上传而采用微信小程序直传。
联通云OSS官方文档
此时小程序端需要向应用服务端获取签名,获取签名方法详见
以下是Java生成签名代码部分
/**
* 获取oss认证签名
* @author DdogRing
* @date 2022/4/13 0013 16:21
* @param
* @return java.util.Map<java.lang.String,java.lang.Object>
*/
public Map<String, Object> getSignature() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Calendar calendar = Calendar.getInstance();
// policy有效期10分钟
calendar.add(Calendar.MINUTE, - (8 * 60) + 10);
Date time = calendar.getTime();
String format = sdf.format(time);
// 生成policy
String policy = "{\"expiration\": \""+ format +"\",\"conditions\": [[\"eq\",\"$bucket\", \""
+ bucketName + "\" ],[\"starts-with\", \"$key\", \"" + objectName
+ "\"],[\"content-length-range\", 0, 104857600],[\"eq\",\"$Content-Type\", \"text/plain\"],{\"acl\":\""
+ CannedAccessControlList.Private +"\"}]}";
// policy加密
String encodePolicy = new String(Base64.getEncoder().encode(policy.getBytes()));
// 计算签名
String signature = computeSignature(accessKeySecret, encodePolicy);
Map<String, Object> res = new HashMap<>();
res.put("accessKeyId", "accessKey");
res.put("encodePolicy", encodePolicy);
res.put("signature", signature);
res.put("filename", objectName);
return res;
}
/**
* 计算签名
* @author DdogRing
* @date 2022/4/13 0013 16:22
* @param key accessKeySecret
* @param data base64后的policy
* @return java.lang.String
*/
public String computeSignature(String key, String data) {
try {
byte[] signData = sign(key.getBytes(DEFAULT_ENCODING), data.getBytes(DEFAULT_ENCODING), macInstance, LOCK,
ALGORITHM);
return BinaryUtils.toBase64(signData);
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Unsupported algorithm: " + DEFAULT_ENCODING, ex);
}
}
protected byte[] sign(byte[] key, byte[] data, Mac macInstance, Object lock, String algorithm) {
try {
if (macInstance == null) {
synchronized (lock) {
if (macInstance == null) {
macInstance = Mac.getInstance(algorithm);
}
}
}
Mac mac;
try {
mac = (Mac) macInstance.clone();
} catch (CloneNotSupportedException e) {
mac = Mac.getInstance(algorithm);
}
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data);
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException("Unsupported algorithm: " + algorithm, ex);
} catch (InvalidKeyException ex) {
throw new RuntimeException("Invalid key: " + key, ex);
}
}
总结
联通云OSS对象存储的官方文档还有待完善(很多地方其实是有出入的),最后都是翻阅亚马逊S3的文档、阿里云OSS文档和联系联通云的技术专家解决的。