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上的命名空间,相当于数据的容器,可以存 ...
随机推荐
- C语言文件读写总结
主要有四种: 1.文件的字符输入输出函数 fgetc fputc2.文件的字符串输入输出函数 fgets fputs3.文件的格式化输入输出函数 fscanf fprintf4.文件的数据块输入输出函 ...
- 卸载asterisk 会装就要会卸载 你会吗? [跟我一起学](转安静的发狂者)
1 针对用编译的方式安装时的卸载 第一步 :先停止你的asterisk >asterisk -rx ‘stop now’然后要验证一下是否真的被停了. >ps aux|grep “as ...
- AutoIt中ControlFocus的使用
在使用AutoIt最控件做自动化操作的时候,经常性的会碰到无法使用Windows Info工具获取控件的属性,但是我们又需要获取该控件的焦点,我们该怎么办呢? 方法1: 应用controlFocus方 ...
- Asset Catalog Help (九)---Changing Image Set Names
Changing Image Set Names Use the Attributes inspector to edit a set’s name. 使用属性检查器(Attributes inspe ...
- Git小白到老鸟的进阶之路
点"计算机视觉life"关注,置顶更快接收消息! 小白:师兄,师兄,上次你教我的操作,我傻乎乎的执行了一遍,可是那个Git究竟是什么那? 师兄:小白莫慌,Git就是一种版本控制,小 ...
- E20181120-hm
checkerboard n. 西洋跳棋盘; checker n. 方格图案;
- lightoj 1076 【二分找满足条件的最左】
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ...
- XCode5 编译ffmpeg流程
今天想在Mac10.9 XCode5的环境下把ffmpeg编译出来,本来以为很好搞定,结果版本一升级,以前的命令行不通了,出各种错误.折腾了三四个小时,最后终于成功了. 编译流程: 1.ffmpeg官 ...
- 【BZOJ1122】[POI2008] 账本BBB
→传送门← 正解: 贪心加单调队列优化 先粘贴一张别人写的被老师发下来给我们的题解(就是看着这张题解才写出来的) 下面是自己的话(一些具体操作过程): 把环拆成一条2*n的链,然后用优先队列来求出每一 ...
- C#连接Sybase数据库,Anywhere 8
数据库版本是Adaptive Server Anywhere 8 1.添加引用,程序集 iAnywhere.Data.AsaClient.dll文件在数据库的安装目录下,例如:C:\Program F ...