Java项目接入阿里云OSS存储

时间:2023-03-09 16:48:05
Java项目接入阿里云OSS存储

需求背景

目前公司内部项目所支持的文件云存储方式还是公司内部项目组提供的方案,但在时间的考验之下,弊端显现,尤其是灾备切换过程中需要切换访问地址,这种操作不方便,更可能因为中间过程的失误导致资源不可用,而且这种操作也会带来资源可用的延时,仔细斟酌发现这种操作似乎并不合逻辑。

在众多项目组的千呼万唤之下,阿里云的OSS存储方案进入了我们的视线,依托公共云环境,屏蔽项目本身切换状态可能带来的资源不可用的问题,将资源存储与访问独立出来,极大的与企业自有项目解耦,同时降低企业自身项目运行状态对公共资源访问的影响。

项目接入

Captain的本项目基于JDK1.8,采用SpringBoot框架开发。

前期准备

从阿里云平台获取到endpoint、accessKeyId、accessKeySecret相关配置信息,因为只有在这些信息的支持下,才能展开后续功能的开发。

创建bucket(存储命名空间、平台唯一才行),可以在阿里云操作台建立,也可以通过代码生成。

Maven依赖

 <dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>

属性配置

可以将和环境相关的固定配置类信息放置于properties文件中:

# aliyun oss
aliyun.oss.endpoint="http://oss-cn-hangzhou.aliyuncs.com"
aliyun.oss.keyid=<yourAccessKeyId>
aliyun.oss.keysecret=<yourAccessKeySecret>
aliyun.oss.bucketname=<yourBucketName> # aliyun filehost based on dev/test/prod(tha/idn)
aliyun.oss.filehost=dev

编写工具类

 /**
* @Project: captain-supply-chain
* @PackageName: com.captain.supply-chain.common.file
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @DateTime: 2019/5/10 18:12.
* @Description: Upload file to Aliyun OSS.
*/
@Slf4j
@Component
public class AliyunOssService { /**
* 斜杠
*/
private final String FLAG_SLANTING_ROD = "/";
/**
* http://
*/
private final String FLAG_HTTP = "http://";
/**
* https://
*/
private final String FLAG_HTTPS = "https://";
/**
* 空字符串
*/
private final String FLAG_EMPTY_STRING = "";
/**
* 点号
*/
private final String FLAG_DOT = ".";
/**
* 横杠
*/
private final String FLAG_CROSSBAR = "-"; /**
* 缺省的最大上传文件大小:20M
*/
private final int DEFAULT_MAXIMUM_FILE_SIZE = 20; /**
* endpoint
*/
@Value("${aliyun.oss.endpoint}")
private String endpoint; /**
* access key id
*/
@Value("${aliyun.oss.keyid}")
private String accessKeyId; /**
* access key secret
*/
@Value("${aliyun.oss.keysecret}")
private String accessKeySecret; /**
* bucket name (namespace)
*/
@Value("${aliyun.oss.bucketname}")
private String bucketName; /**
* file host (dev/test/prod)
*/
@Value("${aliyun.oss.filehost}")
private String fileHost; @Autowired
protected GetSetCacheService getSetCacheService; /**
* 以文件流的方式上传文件
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param fileName 文件名称
* @param filePath 文件路径
* @param inputStream 文件输入流
* @return
*/
public String uploadFile(String fileName, String filePath, InputStream inputStream) {
return coreUpload(fileName, filePath, inputStream);
} /**
* 核心上传功能
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param fileName 文件名
* @param filePath 文件路径
* @param inputStream 文件输入流
* @return
*/
private String coreUpload(String fileName, String filePath, InputStream inputStream) {
log.info("Start to upload file....");
if(StringUtils.isEmpty(fileName) || inputStream == null) {
log.error("Filename Or inputStream is lack when upload file.");
return null;
}
if(StringUtils.isEmpty(filePath)) {
log.warn("File path is lack when upload file but we automatically generated");
String dateCategory = DateUtil.getFormatDate(new Date(), "yyyyMMdd");
filePath = FLAG_SLANTING_ROD.concat(dateCategory).concat(FLAG_SLANTING_ROD);
}
String fileUrl;
OSSClient ossClient = null;
try{ // If the upload file size exceeds the limit
long maxSizeAllowed = getMaximumFileSizeAllowed();
if(Long.valueOf(inputStream.available()) > maxSizeAllowed) {
log.error("Uploaded file is too big.");
return null;
} // Create OSS instance
ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); // Create bucket if not exists
if (!ossClient.doesBucketExist(bucketName)) {
log.info("Bucket '{}' is not exists and create it now.", bucketName);
ossClient.createBucket(bucketName);
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
ossClient.createBucket(createBucketRequest);
} /*********************************/
// List the bucket in my account
//listBuckets(ossClient);
/*********************************/ // File path format
if(!filePath.startsWith(FLAG_SLANTING_ROD)) {
filePath = FLAG_SLANTING_ROD.concat(filePath);
}
if(!filePath.endsWith(FLAG_SLANTING_ROD)) {
filePath = filePath.concat(FLAG_SLANTING_ROD);
} // File url
StringBuilder buffer = new StringBuilder();
buffer.append(fileHost).append(filePath).append(fileName);
fileUrl = buffer.toString();
log.info("After format the file url is {}", fileUrl); // Upload file and set ACL
PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, inputStream));
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
if(result != null) {
log.info("Upload result:{}", result.getETag());
log.info("Upload file {} successfully.", fileName);
}
fileUrl = getHostUrl().concat(fileUrl);
log.info("Call path is {}", fileUrl); /***********************************/
// List objects in your bucket
//listObjects(ossClient);
/***********************************/ }catch (Exception e){
log.error("Upload file failed.", e);
fileUrl = null;
}finally {
if(ossClient != null) {
ossClient.shutdown();
}
}
return fileUrl;
} /**
* 列出buckets下的所有文件
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param ossClient
*/
private void listObjects(OSSClient ossClient) {
System.out.println("Listing objects");
ObjectListing objectListing = ossClient.listObjects(bucketName);
for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
System.out.println(" - " + objectSummary.getKey() + " " +
"(size = " + objectSummary.getSize() + ")");
}
System.out.println();
} /**
* 列出当前用户下的所有bucket
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param ossClient
*/
private void listBuckets(OSSClient ossClient) {
System.out.println("Listing buckets");
ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
listBucketsRequest.setMaxKeys(500);
for (Bucket bucket : ossClient.listBuckets()) {
System.out.println(" - " + bucket.getName());
}
System.out.println();
} /**
* 以文件的形式上传文件
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param fileName
* @param filePath
* @param file
* @return
*/
public String uploadFile(String fileName, String filePath, File file) {
if(file == null) {
log.warn("File is lack when upload.");
return null;
}
if(StringUtils.isEmpty(fileName)) {
log.warn("File name is lack when upload file but we automatically generated");
String uuidFileName = UUID.randomUUID().toString().replace(FLAG_CROSSBAR, FLAG_EMPTY_STRING);
String fname = file.getName();
String suffix = fname.substring(fname.lastIndexOf(FLAG_DOT), fname.length());
fileName = uuidFileName.concat(suffix);
}
InputStream inputStream = null;
String fileUrl = null;
try{
inputStream = new FileInputStream(file);
fileUrl = uploadFile(fileName, filePath, inputStream);
}catch (Exception e){
log.error("Upload file error.", e);
}finally {
IOUtils.safeClose(inputStream);
}
return fileUrl;
} /**
* 获取访问的base地址
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @return
*/
private String getHostUrl() {
String hostUrl = null;
if(this.endpoint.startsWith(FLAG_HTTP)) {
hostUrl = FLAG_HTTP.concat(this.bucketName).concat(FLAG_DOT)
.concat(this.endpoint.replace(FLAG_HTTP, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
} else if (this.endpoint.startsWith(FLAG_HTTPS)) {
return FLAG_HTTPS.concat(this.bucketName).concat(FLAG_DOT)
.concat(this.endpoint.replace(FLAG_HTTPS, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
}
return hostUrl;
} /**
* 获取最大允许上传文件的大小
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @return
*/
private long getMaximumFileSizeAllowed() {
// 缓存单位是M
String maxConfigVal = getSetCacheService.getConfigValue("upload_maximum_file_size");
if(StringUtils.isEmpty(maxConfigVal)) {
return DEFAULT_MAXIMUM_FILE_SIZE * 1024L * 1024L;
}else {
return Long.valueOf(maxConfigVal.trim()) * 1024L * 1024L;
}
} /**
* 删除文件
* @Author: Captain&D
* @cnblogs: https://www.cnblogs.com/captainad
* @param fileUrl 文件访问的全路径
*/
public void deleteFile(String fileUrl) {
log.info("Start to delete file from OSS.{}", fileUrl);
if(StringUtils.isEmpty(fileUrl)
|| (!fileUrl.startsWith(FLAG_HTTP)
&& !fileUrl.startsWith(FLAG_HTTPS))) {
log.error("Delete file failed because the invalid file address. -> {}", fileUrl);
return;
}
OSSClient ossClient = null;
try{
/**
* http:// bucketname dev/test/pic/abc.jpg = key
* http:// captainad.oss-ap-southeast-1.aliyuncs.com/dev/test/pic/abc.jpg
*/
String key = fileUrl.replace(getHostUrl(), FLAG_EMPTY_STRING);
if(log.isDebugEnabled()) {
log.debug("Delete file key is {}", key);
}
ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
ossClient.deleteObject(bucketName, key);
}catch (Exception e){
log.error("Delete file error.", e);
} finally {
if(ossClient != null) {
ossClient.shutdown();
}
}
} }

参考资料

1、https://help.aliyun.com/document_detail/32008.html