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
Java项目接入阿里云OSS存储的更多相关文章
- php将图片存储在阿里云oss存储上
创建两个方法 1.上传方法 use OSS\OssClient; use think\Config; use OSS\Core\OssException; /** * 存储文件 * * @param ...
- 备份MySQL数据库并上传到阿里云OSS存储
1. 环境配置 要将本地文件上传到阿里云oss中, 必须使用阿里云提供的工具 ossutil, 有32位,也有64位的, Linux和Windows都有.具体可以到阿里云官网下载 官网及文档: htt ...
- 前端(react)上传到阿里云OSS存储 实例
需求背景 由于现有的后台管理系统,上传的视频越来越大,加上上传视频较慢,后端小哥提出直接从前端上传视频或者其他文件到阿里云OSS存储. 阿里云OSS 阿里云OSS文档介绍,这里不做过多赘述 安装 原本 ...
- java开发之阿里云对象存储OSS和云数据库Memcache的使用
web开发中标配:aliyun ECS(阿里云服务器),aliyun RDS(阿里云数据库),aliyun OSS(阿里云对象存储),aliyun Memcache(阿里云缓存数据库). 今天就介绍下 ...
- Springboot项目之阿里云OSS快速入门
阿里云oss 阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量.安全.低成本.高可靠的云存储服务.您可以通过本文档提供的简单的REST接口,在任何 ...
- 谷粒 | 10 | 阿里云OSS存储对象服务
阿里云OSS对象存储服务 准备工作 1.在service模块新建子模块service_oss 2.引入pom.xml文件中引入oss服务依赖 <dependencies> <!--a ...
- Laravel 使用阿里云 oss 存储对象
一.下载安装 composer require jacobcyl/ali-oss-storage 二.注册服务提供者 在config/app.php的providers下添加: //阿里云OSS对象存 ...
- 阿里云OSS存储开发(一)
Step 1. 初始化一个OSSClient OSSClient是与OSS服务交互的客户端,SDK的OSS操作都是通过OSSClient完成的. 下面代码新建了一个OSSClient: using A ...
- 阿里云OSS存储
1.accessKeyId 与 accessKeySecret 是由系统分配给用户的,称为ID对,用于标识用户,为访问OSS做签名验证. 2.Bucket是OSS上的命名空间,相当于数据的容器,可以存 ...
随机推荐
- 十五、事务(Transaction)
1.事务是什么? 2.示例 查询事务的隔离级别, 1>会话级(select @@tx_isolation或select @@session.tx_isolation) 2>全局级(sele ...
- How Many Boyfriends
知乎上看到一个问题,如果一个女人说自己集齐了12个星座的男朋友,那么她已经搞过多少男人了. 先考虑这个问题的最简单版本,如果说该女人每一次和12个星座的男人交往的概率相同. 考虑$dp$ 注意到这个问 ...
- Robot FrameWork基础学习(三)
一.关键字(Keyword)根据架构的区分可分为以下三层结构: 底层关键字.公共层关键字.特性关键字. 底层关键字一般与最底层的代码在关系,为上层公共关键字和特性关键字提供接口. 公共层关键字:一般是 ...
- 1.15-1.16 sqoop action
一.sqoop action1 http://oozie.apache.org/docs/4.0.0/DG_SqoopActionExtension.html 1.准备文件 ## [root@hado ...
- ElasticSearch基础+文档CRUD操作
本篇博客是上一篇的延续,主要用来将年前学习ES的知识点做一个回顾,方便日后进行复习和汇总!因为近期项目中使用ES出现了点小问题,因此在这里做一个详细的汇总! [01]全文检索和Lucene (1)全文 ...
- 安装mosquitto报缺少dll文件的错误
解决:下载缺少的dll组件,放到安装目录. 报错:The procedure entry point CRYPTO_memcmp could not be located in the dynami ...
- 1-1 课程简介 & 2-1 IDEA与Eclipse的不同 & 2-3 Intellij IDEA安装
---恢复内容开始--- F:\教程\java-慕课\从网页搭建入门Java Web\Java web\步骤四:常用功能\1.IntelliJ IDEA开发工具入门 1-1 课程简介 2-1 IDEA ...
- CodeForces 359D Pair of Numbers (暴力)
题意:给定一个正整数数组,求最长的区间,使得该区间内存在一个元素,它能整除该区间的每个元素. 析:暴力每一个可能的区间,从数组的第一个元素开始考虑,向两边延伸,设延伸到的最左边的点为l, 最右边的点为 ...
- 移动端UI资源
1.Flat UI Free http://designmodo.github.io/Flat-UI/ 2.POP 原型工具 http://mobilehub.io/products/pop 3.ei ...
- (水题)HDU - 1077 - Catching Fish - 计算几何
http://acm.hdu.edu.cn/showproblem.php?pid=1077 很明显这样的圆,必定有两个点在边界上.n平方枚举圆,再n立方暴力判断.由于没有给T,所以不知道行不行.