1、申请阿里账号,开通oss服务
说明:开通后默认按量收费
2、创建bucket
说明:
调用oss api接口时需要用到buckey名称
存储类型:选择标准存储
读写权限:选择私有(读和写都需要权限),公共读(写要权限,读不需要,直接访问路径可读取)
说明:线上系统间访问可使用内网地址访问
3、设置RAM访问权限
(1)设置访问权限
(2)新建用户
点击用户,创建AccessKey
调用oss api接口时需要用到AccessKeyID和AccessKeySecret、RAM(查看RAM角色详情)
输入手机验证码后会创建AccessKey和相应的密码,需要用户自己保持好AccessKeyID和
AccessKeySecret,之后AccessKeySecret不再显示。
(3)添加权限
说明:这一步可以不做,其实用户可以不做授权,在角色中授权就可以
(4)新建RAM角色
(5)角色添加权限
(6)点击角色名称查看
调用oss api接口时需要用到AccessKeyID和AccessKeySecret、RAM(查看RAM角色详情)
这里有一个属性、roleArn,他呢就是证明是哪个角色的,其实用户可以不做授权,在角色中授权就可以。
4、build.gradle 引入jar
plugins {
id 'org.springframework.boot' version '2.0.4.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.aliyun'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile "org.springframework.boot:spring-boot-configuration-processor",
"com.alibaba:fastjson:1.2.45",
"org.apache.commons:commons-lang3:3.7",
"commons-collections:commons-collections:3.2.2",
/*阿里云对象存储*/
"com.aliyun:aliyun-java-sdk-core:4.0.8",
"com.aliyun.oss:aliyun-sdk-oss:3.1.0",
"com.aliyun.oss:aliyun-java-sdk-sts:3.1.0"
}
5、application.yml配置
#oss配置
aliyun:
bucket: ***-test
ossEndPoint: oss-cn-beijing.aliyuncs.com
# RAM用户(子账号)accessKeyId
accessKeyId: **********Crt
# RAM用户(子账号)accessKeySecret
accessKeySecret: ********************5I0
# RAM用户(子账号)AssumeRole,阿里云STS进行临时授权访问需要
roleArn: acs:ram::********************role
# url过期时间(分钟)
urlExpirationMinute: 10
6、AliyunOssConfig相关代码
package com.aliyun.aliyunoss.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* oss配置
*/
@ConfigurationProperties(prefix = "aliyun")
public class AliyunOssConfig {
private String bucket; //oss bucket
private String ossEndPoint; //oss endpoint
private String accessKeyId; //账号accessKeyId
private String accessKeySecret; //账号accessKeySecret
private String roleArn; //角色ram
private Integer urlExpirationMinute; //url过期时间(分钟)
public String getBucket() {
return bucket;
}
public void setBucket(String bucket) {
this.bucket = bucket;
}
public String getOssEndPoint() {
return ossEndPoint;
}
public void setOssEndPoint(String ossEndPoint) {
this.ossEndPoint = ossEndPoint;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getRoleArn() {
return roleArn;
}
public void setRoleArn(String roleArn) {
this.roleArn = roleArn;
}
public Integer getUrlExpirationMinute() {
return urlExpirationMinute;
}
public void setUrlExpirationMinute(Integer urlExpirationMinute) {
this.urlExpirationMinute = urlExpirationMinute;
}
}
7、AliyunOssStsUtil相关代码
package com.aliyun.aliyunoss.util;
import com.alibaba.fastjson.JSON;
import com.aliyun.aliyunoss.config.AliyunOssConfig;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
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.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.List;
/**
* 阿里云oss工具类
* bucket可设置为私有(读取和写操作需要有权限)、公共读(直接访问路径可读取)
* 通过阿里云STS (Security Token Service) 进行临时授权访问
* 需要在RAM访问控制中创建用户、角色、授权(AliyunOSSFullAccess、AliyunSTSAssumeRoleAccess)
*/
@Component
@EnableConfigurationProperties(AliyunOssConfig.class)
public class AliyunOssStsUtil {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public final static String OSS_ROOT_PATH = "root/";//根目录
@Autowired
private AliyunOssConfig aliyunOssConfig;
/**
* 根据子账号访问权限获取阿里云oss sts临时权限(临时访问凭证),该凭证可保存到缓存中
* @param roleSessionName
* 临时Token的会话名称,RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
* @return 令牌
* @throws ClientException
*/
public AssumeRoleResponse getAssumeRole(String roleSessionName)throws Exception{
try {
// 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
// 只有 RAM用户(子账号)才能调用 AssumeRole 接口
// 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
// 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
IClientProfile profile = DefaultProfile.getProfile("",aliyunOssConfig.getAccessKeyId() , aliyunOssConfig.getAccessKeySecret());
DefaultAcsClient client = new DefaultAcsClient(profile);
// 创建一个 AssumeRoleRequest 并设置请求参数
final AssumeRoleRequest request = new AssumeRoleRequest();
// request.setVersion(aliyunOssSTS_API_VERSION);
request.setMethod(MethodType.POST);
// 此处必须为 HTTPS
request.setProtocol(ProtocolType.HTTPS);
// RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
// 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '_' 字母和数字等字符
// 具体规则请参考API文档中的格式要求
// 临时Token的会话名称,自己指定用于标识你的用户,主要用于区分Token颁发给谁
// acs:ram::$accountID:role/$roleName
request.setRoleSessionName(roleSessionName);
// RoleArn 需要在 RAM 控制台上获取
request.setRoleArn(aliyunOssConfig.getRoleArn());
// 授权策略
//request.setPolicy(readJson(aliyunOssPolicyFile));
// 设置token时间(最小15分钟,最大1小时) The Min/Max value of DurationSeconds is 15min/1hr
//request.setDurationSeconds(60 * 60L);
// 发起请求,并得到response
final AssumeRoleResponse assumeRoleResponse = client.getAcsResponse(request);
System.out.println("临时账号ID getAccessKeyId()=============" + assumeRoleResponse.getCredentials().getAccessKeyId());
System.out.println("临时密码 getAccessKeySecret()=============" + assumeRoleResponse.getCredentials().getAccessKeySecret());
System.out.println("临时token getSecurityToken()=============" + assumeRoleResponse.getCredentials().getSecurityToken());
System.out.println("有效时间 getExpiration()=============" + assumeRoleResponse.getCredentials().getExpiration());
logger.info("assumeRoleResponse ======\n{}",JSON.toJSONString(assumeRoleResponse));
return assumeRoleResponse;
}catch (Exception e){
throw e;
}
}
/**
* 获取ossClient客户端
* @param roleSessionName 临时Token的会话名称,RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
* @return
*/
public OSSClient getOssClient(String roleSessionName){
try {
AssumeRoleResponse assumeRoleResponse = this.getAssumeRole(roleSessionName);
// 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
// 创建OSSClient实例。
return new OSSClient(aliyunOssConfig.getOssEndPoint(), new DefaultCredentialProvider(assumeRoleResponse.getCredentials().getAccessKeyId(), assumeRoleResponse.getCredentials().getAccessKeySecret(), assumeRoleResponse.getCredentials().getSecurityToken()), null);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 获取文件资源url(签名)
* @param ossFilePath
* @param roleSessionName
* @return 返回经过签名的资源url
*/
public String getOssSignUrl(String ossFilePath,String roleSessionName){
OSSClient ossClient = null;
try{
ossClient = this.getOssClient(roleSessionName);
// 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。
return this.getOssSignUrl(ossClient,aliyunOssConfig.getBucket(), ossFilePath).toString();
}catch (Exception e){
e.printStackTrace();
}finally {
if(ossClient != null){
// 关闭OSSClient。
ossClient.shutdown();
}
}
return "";
}
/**
* 获取文件资源url(签名)
* @param bucketName
* @param ossFilePath
* @param roleSessionName
* @return 返回经过签名的资源url
*/
public String getOssSignUrl(String bucketName,String ossFilePath,String roleSessionName){
OSSClient ossClient = null;
try{
ossClient = this.getOssClient(roleSessionName);
// 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。
return this.getOssSignUrl(ossClient,bucketName, ossFilePath).toString();
}catch (Exception e){
e.printStackTrace();
}finally {
if(ossClient != null){
// 关闭OSSClient。
ossClient.shutdown();
}
}
return "";
}
/**
* 返回oss 签名URL
* @param ossClient
* @param bucketName
* @param ossFilePath
* @return
*/
public URL getOssSignUrl(OSSClient ossClient,String bucketName,String ossFilePath){
//默认1小时
int urlExpirationMinute = 60;
if(aliyunOssConfig.getUrlExpirationMinute() != null && aliyunOssConfig.getUrlExpirationMinute() > 0){
urlExpirationMinute = aliyunOssConfig.getUrlExpirationMinute();
}
// 设置URL过期时间为1小时。
Date expiration = new Date(new Date().getTime() + (urlExpirationMinute * 60 * 1000 ));
// 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。
return ossClient.generatePresignedUrl(bucketName, ossFilePath, expiration);
}
/**
* 上传文件
* @param roleSessionName
* @param sourceFile
* @param ossFilePath
* @return
*/
public String uploadObjectToOss(String roleSessionName,File sourceFile, String ossFilePath){
String url ="";
FileInputStream inputStream = null;
ByteArrayOutputStream outputStream = null;
try {
inputStream = new FileInputStream(sourceFile);
outputStream = new ByteArrayOutputStream();
byte [] bytes = new byte[1024];
int temp;
while((temp = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,temp);
}
url = this.uploadObjectToOss(roleSessionName,ossFilePath,outputStream.toByteArray());
}catch (Exception e){
e.printStackTrace();
}finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return url;
}
/**
* 上传文件
* @param roleSessionName 临时会话名称,用于标识用户token
* @param ossFilePath
* @param bytes
* @return
*/
public String uploadObjectToOss(String roleSessionName,String ossFilePath, byte[] bytes){
OSSClient ossClient = null;
try {
ossClient = this.getOssClient(roleSessionName);
//判断bucketName是否存储,如果不存在则创建
boolean isExist = ossClient.doesBucketExist(aliyunOssConfig.getBucket());
if(!isExist){
ossClient.createBucket(aliyunOssConfig.getBucket());
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ossClient.putObject(aliyunOssConfig.getBucket(), ossFilePath, byteArrayInputStream, null);
String url = this.getOssSignUrl(ossClient,aliyunOssConfig.getBucket(), ossFilePath).toString();
logger.info("域名和文件路径且签名加密:\n{}", url);
// "http://你的BucketName.你的Endpoint/自定义路径/" + fileName;
String fileDomainUrl = "http://".concat(aliyunOssConfig.getBucket()).concat(".").concat(aliyunOssConfig.getOssEndPoint());
String fileUrl = fileDomainUrl.concat("/").concat(ossFilePath);
logger.info("域名路径:\n{}", fileDomainUrl);
logger.info("域名和文件路径:\n{}", fileUrl);
logger.info("文件路径:\n{}", ossFilePath);
return fileUrl;
} catch (Exception e) {
e.printStackTrace();
}finally{
this.closeOssClient(ossClient);
}
return "";
}
/**
* 关闭客户端
* @param ossClient
*/
public void closeOssClient(OSSClient ossClient){
if(ossClient != null){
ossClient.shutdown();
}
}
/**
* 删除某个Object
* @param roleSessionName
* @param bucketUrl
* @return
*/
public boolean deleteObject(String roleSessionName,String bucketUrl) {
OSSClient client = null;
try {
client = this.getOssClient(roleSessionName);
// 删除Object.
client.deleteObject(aliyunOssConfig.getBucket(), bucketUrl);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
closeOssClient(client);
}
return true;
}
/**
* 删除多个Object
*
* @param roleSessionName
* @param bucketUrls
* @return
*/
public boolean deleteObjects(String roleSessionName,List bucketUrls) {
OSSClient client = null;
try {
client = this.getOssClient(roleSessionName);
// 删除Object.
DeleteObjectsResult deleteObjectsResult = client.deleteObjects(new DeleteObjectsRequest(aliyunOssConfig.getBucket()).withKeys(bucketUrls));
List deletedObjects = deleteObjectsResult.getDeletedObjects();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
client.shutdown();
}
return true;
}
}
8、AliyunOssController相关代码
package com.aliyun.aliyunoss.controller;
import com.aliyun.aliyunoss.util.AliyunOssStsUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* oss文件接口调用
*/
@RequestMapping("/ossFile")
@RestController
public class AliyunOssController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//排除上传的文件类型
public static final List EXCLUDE_FILE = Arrays.asList(new String[]{"jsp","classes","css","html"});
@Autowired
private AliyunOssStsUtil ossStsUtil;
/**
* 文件上传
* @param request
* @param module
* @return 返回文件路径
*/
@PostMapping("upload")
@ResponseBody
public List uploadFile(HttpServletRequest request,String module){
Long userId = 1L;
List filePathList = new ArrayList<>();
MultipartHttpServletRequest multipartHttpServletRequest = null;
try{
multipartHttpServletRequest = (MultipartHttpServletRequest) request;
Map fileMap = multipartHttpServletRequest.getFileMap();
for(String key : fileMap.keySet()){
MultipartFile file = multipartHttpServletRequest.getFile(key);
if(file == null){
continue;
}
String fileName = file.getOriginalFilename();
String lastName = fileName.substring(fileName.lastIndexOf(".")+1);
if(file != null && EXCLUDE_FILE.contains(lastName)){
logger.info("不支持相关格式,文件名为:" + fileName);
throw new RuntimeException("不支持相关格式,文件名为:" + fileName);
}
//如果name为空时,取md5值
if(!StringUtils.isNotBlank(fileName)){
fileName = DigestUtils.md5DigestAsHex(file.getInputStream());
}
//文件存放的模块目录
module = StringUtils.isNotBlank(module) ? module:"default";
String ossFilePath = AliyunOssStsUtil.OSS_ROOT_PATH.concat(module.concat("/").concat(fileName));
String url = ossStsUtil.uploadObjectToOss(String.valueOf(userId),ossFilePath,file.getBytes());
filePathList.add(url);
}
}catch (Exception e){
logger.error("上传出错", e);
e.printStackTrace();
}
return filePathList;
}
/**
* 获取文件签名路径测试
* @return
*/
@GetMapping("/getFileUrl")
public String getFileSignUrl(){
try {
String fileName = AliyunOssStsUtil.OSS_ROOT_PATH + "test/滴滴电子发票_20190508184729.pdf";
return ossStsUtil.getOssSignUrl(fileName,"123");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 上传测试
* @return
*/
@GetMapping("/uploadTest")
public String uploadTest(){
try {
String filePath = "E:\\发票\\滴滴电子发票.pdf";
String fileName = AliyunOssStsUtil.OSS_ROOT_PATH + "test/滴滴电子发票_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".pdf";
String url = this.ossStsUtil.uploadObjectToOss("user001",new File(filePath),fileName);
return url;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 删除文件测试
* @param ossFilePath
* @return
*/
@GetMapping("/delete")
@ResponseBody
public String delete(String ossFilePath){
try {
boolean flag = ossStsUtil.deleteObject("001",ossFilePath);
logger.info("删除文件=====\n{}",ossFilePath);
return flag ? "删除成功!":"删除失败!";
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}