目录
1.前提
注册阿里云账号,登录之后在右上角找到控制台并点击
进入页面
点击开始免费试用进入页面找到对象存储OSS免费试用
点击后购买即可,建议绑定支付宝可以顺便实名认证了
然后点击控制台回到控制台页面,鼠标左上角悬浮菜单栏出现以下界面,在产品与服务的搜索框搜索 对象存储 进入OSS管理控制台
2.OSS存储的创建
点击Bucket列表,然后点击创建Bucket
在创建界面填写名称,关闭阻止公共访问,并且将读写权限改为公共读即可完成创建
地域可改可不改
3.SDK的安装
在Maven工程中使用OSS Java SDK,在pom.xml中加入以下依赖即可
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
如果使用的是Java 9及以上的版本,则需要添加JAXB相关依赖。添加JAXB相关依赖示例代码如下:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
4.配置访问凭证(使用STS)
4.1创建用户
登录RAM控制台,在左侧导航栏,点击用户后在用户界面点击创建用户
填写完登录名称和显示名称后勾选OpenAPI调用访问,确定后完成安全验证即可
4.2为RAM用户授予请求AssumeRole的权限
单击已创建RAM用户右侧对应的添加权限,在新增授权页面,搜索AliyunSTSAssumeRoleAccess系统策略,勾选后确认新增即可
4.3为RAM用户创建AccessKey
回到用户界面,点击刚刚创建的用户,在认证管理页签下的AccessKey区域,单击创建AccessKey。
根据界面提示完成安全验证,在创建AccessKey对话框,查看AccessKey ID和AccessKey Secret,建议单击下载CSV文件,下载AccessKey信息。或者选择单击复制,复制AccessKey信息。
4.4创建阿里云账号(主账号)的AccessKey
鼠标悬浮在右上方的账号图标上,单击AccessKey管理。
在安全提示对话框,阅读安全提示信息,然后单击继续使用AccessKey,在AccessKey页面,单击创建AccessKey即可(流程与为RAM用户创建AccessKey基本一致)
4.5创建RAM角色
进入RAM控制台,点击左栏角色右边显示角色界面,点击创建角色,选择阿里云账号点击下一步,输入角色名称后点击完成,关闭。在角色页面点击刚刚创建的角色,复制ARN,关闭
4.6为RAM角色授予上传文件的权限
4.6.1创建权限
点击左侧的权限策略,在该页面
创建权限策略,在创建权限策略页面,单击脚本编辑,然后在策略文档输入框中赋予角色上传文件到examplebucket的权限。注意examplebucket需要更改为你最先创建的bucket
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject"
],
"Resource": [
"acs:oss:*:*:examplebucket/*"
]
}
]
}
策略配置完成后,单击继续编辑基本信息,在基本信息区域,填写策略名称,然后单击确定。
4.6.2授予权限
点击左侧角色,为刚刚创建的角色授予权限,点击新增授权,点击自定义策略,勾选刚刚创建的权限,确认授权即可
5.获取临时访问凭证(官方提供的需要设置环境变量)
package com.enjoy.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
public class StsServiceSample {
public static void main(String[] args) {
// STS服务接入点,例如sts.cn-hangzhou.aliyuncs.com。您可以通过公网或者VPC接入STS服务。
String endpoint = "sts.cn-hangzhou.aliyuncs.com";
//你的角色accessKeyId
String accessKeyId = "";
//你的角色accessKeySecret
String accessKeySecret = "";
//你的角色roleArn
String roleArn = "";
//会话名
String roleSessionName = "test";
// 临时访问凭证将获得角色拥有的所有权限。
String policy = null;
// 临时访问凭证的有效时间,单位为秒。最小值为900,最大值以当前角色设定的最大会话时间为准。
// 当前角色最大会话时间取值范围为3600秒~43200秒,默认值为3600秒。
Long durationSeconds = 3600L;
try {
// 发起STS请求所在的地域。建议保留默认值,默认值为空字符串("")。
String regionId = "";
// 添加endpoint。适用于Java SDK 3.12.0及以上版本。
DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
// 构造default profile。
IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
// 构造client。
DefaultAcsClient client = new DefaultAcsClient(profile);
// 创建AssumeRoleRequest对象,用于指定请求参数。
final AssumeRoleRequest request = new AssumeRoleRequest();
// 设置请求方法为POST。适用于Java SDK 3.12.0及以上版本。
request.setSysMethod(MethodType.POST);
// 设置要扮演的角色的ARN。
request.setRoleArn(roleArn);
// 设置角色会话名称,用于区分不同的令牌。
request.setRoleSessionName(roleSessionName);
// 设置权限策略。这里使用null表示不指定特定策略,即获取角色默认的权限。
request.setPolicy(policy);
// 设置临时凭证的有效时间,单位为秒。
request.setDurationSeconds(durationSeconds);
// 发送请求并获取响应。
final AssumeRoleResponse response = client.getAcsResponse(request);
// 打印获取到的临时凭证信息。
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
} catch (ClientException e) {
// 捕获异常并输出错误信息。
System.out.println("Failed:");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
System.out.println("RequestId: " + e.getRequestId());
}
}
}
如果希望临时访问凭证在获得角色拥有的权限后,进一步限制权限范围,例如角色被授予了上传文件到你的bucket的权限,需要限制临时访问凭证只能向该Bucket下的某个目录上传文件,可以通过参考以下示例设置policy。
// 以下Policy用于限制仅允许使用临时访问凭证向examplebucket下的src目录上传文件。
// 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至examplebucket下的src目录。
String policy = "{\n" +
" \"Version\": \"1\", \n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": [\n" +
" \"oss:PutObject\"\n" +
" ], \n" +
" \"Resource\": [\n" +
" \"acs:oss:*:*:examplebucket/src/*\" \n" +
" ], \n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
6.使用临时访问凭证上传文件至OSS
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyuncs.exceptions.ClientException;
import java.io.File;
public class Demo {
public static void main(String[] args) throws ClientException {
// OSS访问域名。以华东1(杭州)地域为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取步骤5生成的临时访问密钥AccessKey ID和AccessKey Secret,非阿里云账号AccessKey ID和AccessKey Secret。
String accessKeyId = "OSS_ACCESS_KEY_ID";
String accessKeySecret = "OSS_ACCESS_KEY_SECRET";
// 从环境变量中获取步骤5生成的安全令牌SecurityToken。
String securityToken = "OSS_SESSION_TOKEN";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
// 将本地文件exampletest.txt上传至examplebucket(你的bucket)。
PutObjectRequest putObjectRequest = new PutObjectRequest("examplebucket", "exampletest.txt", new File("D:\\localpath\\exampletest.txt"));
// ObjectMetadata metadata = new ObjectMetadata();
// 上传文件时设置存储类型。
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// 上传文件时设置读写权限ACL。
// metadata.setObjectAcl(CannedAccessControlList.Private);
// putObjectRequest.setMetadata(metadata);
try {
// 上传文件。
ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
7.将配置获取访问凭证与上传文件功能(返回URL)封装为工具类(建议使用7.2版本)
7.1 需要手动刷新来获取临时凭证
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
private String oosEndpoint;
private String stsEndpoint;
private String accessKeyId;
private String accessKeySecret;
private String roleArn;
private String bucketName;
}
#yml
#阿里云OSS
aliyun:
oss:
oosEndpoint: https://oss-cn-chengdu.aliyuncs.com
stsEndpoint: sts.cn-chengdu.aliyuncs.com
accessKeyId:
accessKeySecret:
roleArn:
bucketName:
package com.enjoy.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
@Component
public class OSSUtils {
@Autowired
private AliOSSProperties aliOSSProperties;
/**
* 获取临时访问凭证。
*
* @param roleSessionName 角色会话名称,用于区分不同的令牌
* @param durationSeconds 临时凭证的有效时间,单位为秒
* @param policy 权限策略,传入null表示获取角色默认的权限
* @return 临时访问凭证的响应对象
*/
public AssumeRoleResponse getTemporaryCredentials(String roleSessionName, Long durationSeconds, String policy) {
try {
String regionId = "";
DefaultProfile.addEndpoint(regionId, "Sts", aliOSSProperties.getStsEndpoint());
IClientProfile profile = DefaultProfile.getProfile(regionId, aliOSSProperties.getAccessKeyId(), aliOSSProperties.getAccessKeySecret());
DefaultAcsClient client = new DefaultAcsClient(profile);
AssumeRoleRequest request = new AssumeRoleRequest();
request.setSysMethod(MethodType.POST);
request.setRoleArn(aliOSSProperties.getRoleArn());
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy);
request.setDurationSeconds(durationSeconds);
return client.getAcsResponse(request);
} catch (ClientException e) {
// 捕获异常并输出错误信息。
System.err.println("无法获取临时凭证:");
System.err.println("Error code: " + e.getErrCode());
System.err.println("Error message: " + e.getErrMsg());
System.err.println("RequestId: " + e.getRequestId());
return null;
}
}
/**
* 上传文件到OSS,并返回文件的URL。
*
* @param file 上传的文件
* @return 文件的URL,上传失败返回null
*/
public String uploadFile(MultipartFile file) {
// 获取临时访问凭证
AssumeRoleResponse response = getTemporaryCredentials("test", 3600L, null);
if (response == null) {
System.err.println("获取临时访问凭证失败,无法上传文件。");
return null;
}
String endpoint = aliOSSProperties.getOosEndpoint();
String accessKeyId = response.getCredentials().getAccessKeyId();
String accessKeySecret = response.getCredentials().getAccessKeySecret();
String securityToken = response.getCredentials().getSecurityToken();
String bucketName = aliOSSProperties.getBucketName();
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
try {
// 避免文件覆盖,生成带UUID的新文件名
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 获取上传文件的输入流
InputStream inputStream = file.getInputStream();
// 构造上传文件请求
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
// 执行文件上传
ossClient.putObject(putObjectRequest);
// 生成文件的URL
String fileUrl = "https://" + bucketName + "." + endpoint.replace("https://", "") + "/" + fileName;
System.out.println("文件上传成功。文件URL:" + fileUrl);
return fileUrl;
} catch (OSSException | IOException oe) {
System.err.println("文件上传失败:" + oe.getMessage());
} finally {
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}
}
7.2 项目启动,自动获取临时凭证,临时凭证自动刷新
import com.aliyun.credentials.Client;
import com.aliyun.credentials.models.Config;
import com.aliyun.credentials.models.CredentialModel;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.Credentials;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentials;
import com.aliyun.oss.common.comm.SignVersion;
import com.enjoy.entity.AliOSSProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class AliyunCredentialsUtil {
private final AliOSSProperties aliOSSProperties;
private CredentialsProvider credentialsProvider;
@Autowired
public AliyunCredentialsUtil(AliOSSProperties aliOSSProperties) {
this.aliOSSProperties = aliOSSProperties;
getTemporaryCredentials(); // 在构造函数中获取临时凭证
}
private void getTemporaryCredentials() {
try {
Config config = new Config();
config.setType("ram_role_arn");
config.setRoleArn(aliOSSProperties.getRoleArn());
config.setAccessKeyId(aliOSSProperties.getAccessKeyId());
config.setAccessKeySecret(aliOSSProperties.getAccessKeySecret());
config.setRoleName(aliOSSProperties.getRoleSessionName());
final Client credentialsClient = new Client(config);
credentialsProvider = new CredentialsProvider() {
@Override
public Credentials getCredentials() {
CredentialModel credential = credentialsClient.getCredential();
return new DefaultCredentials(credential.getAccessKeyId(), credential.getAccessKeySecret(), credential.getSecurityToken());
}
@Override
public void setCredentials(Credentials credentials) {
}
};
log.info("成功获取临时凭证" + credentialsProvider);
} catch (Exception e) {
log.error("获取临时凭证失败", e);
throw new RuntimeException("无法初始化凭证提供者", e);
}
}
public OSS createOSSClient() {
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(aliOSSProperties.getEndpoint())
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(aliOSSProperties.getRegion())
.build();
return ossClient;
}
}
7.3 基于7.2版本实现的文件上传、下载、删除工具
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.enjoy.entity.AliOSSProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
@Slf4j
@Component
public class OSSUtils {
@Autowired
private AliOSSProperties aliOSSProperties;
@Autowired
private AliyunCredentialsUtil aliyunCredentialsUtil;
public String uploadFile(MultipartFile file) {
String bucketName = aliOSSProperties.getBucketName();
OSS ossClient = aliyunCredentialsUtil.createOSSClient();
String endpoint = aliOSSProperties.getEndpoint();
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
try {
InputStream inputStream = file.getInputStream();
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
ossClient.putObject(putObjectRequest);
String fileUrl = "https://" + bucketName + "." + endpoint.replace("https://", "") + "/" + fileName;
System.out.println("文件上传成功。文件URL:" + fileUrl);
return fileUrl;
} catch (OSSException oe) {
log.error("OSS异常,Error Message: {},Error Code: {},Request ID: {},Host ID: {}",
oe.getErrorMessage(), oe.getErrorCode(), oe.getRequestId(), oe.getHostId());
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}
public void downloadFile(String objectName) {
String bucketName = aliOSSProperties.getBucketName();
OSS ossClient = aliyunCredentialsUtil.createOSSClient();
String downloadPath = "D:\\file\\";
try {
OSSObject ossObject = ossClient.getObject(bucketName, objectName);
InputStream content = ossObject.getObjectContent();
if (content != null) {
// 创建保存文件的路径
File downloadFile = new File(downloadPath + objectName);
// 创建文件输出流
FileOutputStream outputStream = new FileOutputStream(downloadFile);
byte[] buffer = new byte[1024];
int length;
// 读取流内容并写入文件
while ((length = content.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
// 关闭输出流和输入流
outputStream.close();
content.close();
log.info("文件下载成功,保存路径:{}", downloadFile.getAbsolutePath());
}
} catch (OSSException oe) {
log.error("OSS异常,Error Message: {},Error Code: {},Request ID: {},Host ID: {}",
oe.getErrorMessage(), oe.getErrorCode(), oe.getRequestId(), oe.getHostId());
} catch (ClientException ce) {
log.error("客户端异常,Error Message: {}", ce.getMessage());
} catch (Exception e) {
log.error("文件下载失败", e);
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}