官网:https://help.aliyun.com/document_detail/31927.html
对象存储可选方式:服务端上传、客户端直传oss、客户端直传oss并设置回调url
客户端直传oss,设置回调url
# 获取签名(policy)和回调参数
客户端向后端服务器获取签名信息,后端服务器返回签名信息、回调参数
# 客户端直传到oss
客户端直接将对象上传到oss服务器,附带回调参数;
oss根据回调参数,想后端服务器发送回调请求(请求参数如文件路径、大小等);
应用服务器验证回调请求的authorization,验证通过向oss服务器返回响应数据
# oss向客户端返回响应数据
oss服务器收到应用服务器的响应数据后,将响应数据发送给客户端
客户端向应用服务请求获取policy、回调参数
# 获取policy、回调的应用地址
serverUrl = 'http://88.88.88.88:8888'
应用服务器返回policy、回调参数(body部分)
{
"accessid":"LTAI5tAzivUnv4ZF1azP****",
"host":"http://post-test.oss-cn-hangzhou.aliyuncs.com",
"policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****",
"signature":"I2u57FWjTKqX/AE6doIdyff1****",
"expire":1446727949,
"callback":"eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9vc3MtZGVtby5hbGl5dW5jcy5jb206MjM0NTAiLAoiY2FsbGJhY2tCb2R5IjoiZmlsZW5hbWU9JHtvYmplY3R9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZoZWlnaHQ9JHtpbWFnZUluZm8uaGVpZ2h0fSZ3aWR0aD0ke2ltYWdlSW5mby53aWR0aH0iLAoiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCJ9",
"dir":"user-dirs/"
}
callback使用Base64编码,解码后内容如下
{
"callbackUrl":"http://oss-demo.aliyuncs.com:23450",
"callbackBody":"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
"callbackBodyType":"application/x-www-form-urlencoded"
}
客户端向oss发送文件
new_multipart_params = {
'key' : key + '${filename}',
'policy': policyBase64,
'OSSAccessKeyId': accessid,
// 设置服务端返回状态码为200,不设置则默认返回状态码204。
'success_action_status' : '200',
'callback': callbackbody,
'signature': signature,
};
oss根据回调设置,发送回调请求给应用服务器
Hypertext Transfer Protocol
POST / HTTP/1.1\r\n
Host: 47.97.168.53\r\n
Connection: close\r\n
Content-Length: 76\r\n
Authorization: fsNxFF0w******MNAoFb//a8x6v2lI1******h3nFUDALgku9bhC+cWQsnxuCo******tBUmnDI6k1PofggA4g==\r\n
//应用服务器验证authorization,验证通过后返回响应数据
Content-MD5: eiEMyp7lbL8KStPBzMdr9w==\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Date: Sat, 15 Sep 2018 10:24:12 GMT\r\n
User-Agent: aliyun-oss-callback\r\n
x-oss-additional-headers: \r\n
x-oss-bucket: signedcallback\r\n
x-oss-owner: 137918634953****\r\n
x-oss-pub-key-url: aHR0cDovL2dvc3NwdWJsaWMuYWxpY2RuLmNvbS9jYWxsYmFja19wdWJfa2V5X3YxLnaH****\r\n
x-oss-request-id: 534B371674E88A4D8906****\r\n
x-oss-requester: 137918634953****\r\n
x-oss-signature-version: 1.0\r\n
x-oss-tag: CALLBACK\r\n
eagleeye-rpcid: 0.1\r\n
\r\n
[Full request URI: http://47.xx.xx.53/]
[HTTP request 1/1]
[Response in frame: 39]
File Data: 76 bytes
HTML Form URL Encoded: application/x-www-form-urlencoded
Form item: "filename" = ".snappython.png" //文件名称
Form item: "size" = "6014" //文件大小
Form item: "mimeType" = "image/png" //文件类型
Form item: "height" = "221" //文件高度
应用服务器验证authorization,验证通过后返回响应数据
{
"String value": "ok",
"Key": "Status"
}
oss收到响应数据后,将响应数据转发给客户端
com.alibaba.cloud
aliyun-oss-spring-boot-starter
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
com.alibaba.cloud
aliyun-spring-boot-dependencies
${aliyun-spring-boot.version}
pom
import
OssContextAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass(
name = {"com.alibaba.cloud.spring.boot.oss.autoconfigure.OssAutoConfiguration"}
)
@ConditionalOnProperty(
prefix = "alibaba.cloud.oss",
name = {"enabled"},
matchIfMissing = true
)
@EnableConfigurationProperties({OssProperties.class}) //自动创建oss配置类
@ImportAutoConfiguration({AliCloudContextAutoConfiguration.class})
public class OssContextAutoConfiguration {
public OssContextAutoConfiguration() {
}
@ConditionalOnMissingBean
@Bean
public OSS ossClient(AliCloudProperties aliCloudProperties, OssProperties ossProperties) {
//创建ossClient对象
if (ossProperties.getAuthorizationMode() == AliCloudAuthorizationMode.AK_SK) {
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getEndpoint()), "Oss endpoint can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(aliCloudProperties.getAccessKey()), "${alibaba.cloud.access-key} can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(aliCloudProperties.getSecretKey()), "${alibaba.cloud.secret-key} can't be empty.");
return (new OSSClientBuilder()).build(ossProperties.getEndpoint(), aliCloudProperties.getAccessKey(), aliCloudProperties.getSecretKey(), ossProperties.getConfig());
} else if (ossProperties.getAuthorizationMode() == AliCloudAuthorizationMode.STS) {
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getEndpoint()), "Oss endpoint can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getAccessKey()), "Access key can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getSecretKey()), "Secret key can't be empty.");
Assert.isTrue(!StringUtils.isEmpty(ossProperties.getSts().getSecurityToken()), "Security Token can't be empty.");
return (new OSSClientBuilder()).build(ossProperties.getEndpoint(), ossProperties.getSts().getAccessKey(), ossProperties.getSts().getSecretKey(), ossProperties.getSts().getSecurityToken(), ossProperties.getConfig());
} else {
throw new IllegalArgumentException("Unknown auth mode.");
}
}
}
OssProperties
@ConfigurationProperties("alibaba.cloud.oss")
public class OssProperties {
@Value("${alibaba.cloud.oss.authorization-mode:AK_SK}")
private AliCloudAuthorizationMode authorizationMode;
private String endpoint;
private OssProperties.StsToken sts;
private ClientBuilderConfiguration config;
public OssProperties() {
}
********
静态内部类:StsToken
public static class StsToken {
private String accessKey;
private String secretKey;
private String securityToken;
public StsToken() {
}
AliCloudAuthorizationMode:认证枚举
public enum AliCloudAuthorizationMode {
AK_SK,
STS;
private AliCloudAuthorizationMode() {
}
}
ClientBuilderConfiguration
public class ClientBuilderConfiguration extends ClientConfiguration {
public ClientBuilderConfiguration() {
this.supportCname = false;
}
}
ClientConfiguration
public class ClientConfiguration {
public static final String DEFAULT_USER_AGENT = VersionInfoUtils.getDefaultUserAgent();
public static final int DEFAULT_MAX_RETRIES = 3;
public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = -1;
public static final int DEFAULT_CONNECTION_TIMEOUT = 50000;
public static final int DEFAULT_SOCKET_TIMEOUT = 50000;
public static final int DEFAULT_MAX_CONNECTIONS = 1024;
public static final long DEFAULT_CONNECTION_TTL = -1L;
public static final long DEFAULT_IDLE_CONNECTION_TIME = 60000L;
public static final int DEFAULT_VALIDATE_AFTER_INACTIVITY = 2000;
public static final int DEFAULT_THREAD_POOL_WAIT_TIME = 60000;
public static final int DEFAULT_REQUEST_TIMEOUT = 300000;
public static final long DEFAULT_SLOW_REQUESTS_THRESHOLD = 300000L;
public static final boolean DEFAULT_USE_REAPER = true;
public static final String DEFAULT_CNAME_EXCLUDE_LIST = "aliyuncs.com,aliyun-inc.com,aliyun.com";
protected String userAgent;
protected int maxErrorRetry;
protected int connectionRequestTimeout;
protected int connectionTimeout;
protected int socketTimeout;
protected int maxConnections;
protected long connectionTTL;
protected boolean useReaper;
protected long idleConnectionTime;
protected Protocol protocol;
protected String proxyHost;
protected int proxyPort;
protected String proxyUsername;
protected String proxyPassword;
protected String proxyDomain;
protected String proxyWorkstation;
protected boolean supportCname;
protected List cnameExcludeList;
protected Lock rlock;
protected boolean sldEnabled;
protected int requestTimeout;
protected boolean requestTimeoutEnabled;
protected long slowRequestsThreshold;
protected Map defaultHeaders;
protected boolean crcCheckEnabled;
protected List signerHandlers;
public ClientConfiguration() {
this.userAgent = DEFAULT_USER_AGENT;
this.maxErrorRetry = 3;
this.connectionRequestTimeout = -1;
this.connectionTimeout = 50000;
this.socketTimeout = 50000;
this.maxConnections = 1024;
this.connectionTTL = -1L;
this.useReaper = true;
this.idleConnectionTime = 60000L;
this.protocol = Protocol.HTTP;
this.proxyHost = null;
this.proxyPort = -1;
this.proxyUsername = null;
this.proxyPassword = null;
this.proxyDomain = null;
this.proxyWorkstation = null;
this.supportCname = true;
this.cnameExcludeList = new ArrayList();
this.rlock = new ReentrantLock();
this.sldEnabled = false;
this.requestTimeout = 300000;
this.requestTimeoutEnabled = false;
this.slowRequestsThreshold = 300000L;
this.defaultHeaders = new LinkedHashMap();
this.crcCheckEnabled = true;
this.signerHandlers = new LinkedList();
}
AliCloudContextAutoConfiguration
Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({AliCloudProperties.class})
public class AliCloudContextAutoConfiguration {
public AliCloudContextAutoConfiguration() {
}
}
AliCloudProperties
@ConfigurationProperties("alibaba.cloud")
public class AliCloudProperties implements AliCloudConfiguration {
public static final String PROPERTY_PREFIX = "alibaba.cloud";
public static final String ACCESS_KEY_PROPERTY = "alibaba.cloud.access-key";
public static final String SECRET_KEY_PROPERTY = "alibaba.cloud.secret-key";
private String accessKey;
private String secretKey;
public AliCloudProperties() {
}
Oss:oss客户端,对象上传、更新、删除、下载等操作
public interface OSS {
String generatePostPolicy(Date var1, PolicyConditions var2) throws ClientException;
//生成post policy,编码后作为policy返回给前端
String calculatePostSignature(String var1);
//生成signature,作为signature返回给前端
*********
bucket 操作
Bucket createBucket(String var1) throws OSSException, ClientException;
Bucket createBucket(CreateBucketRequest var1) throws OSSException, ClientException;
VoidResult deleteBucket(String var1) throws OSSException, ClientException;
VoidResult deleteBucket(GenericRequest var1) throws OSSException, ClientException;
List listBuckets() throws OSSException, ClientException;
BucketList listBuckets(String var1, String var2, Integer var3) throws OSSException, ClientException;
BucketList listBuckets(ListBucketsRequest var1) throws OSSException, ClientException;
*********
bucket 权限操作
VoidResult setBucketAcl(String var1, CannedAccessControlList var2) throws OSSException, ClientException;
VoidResult setBucketAcl(SetBucketAclRequest var1) throws OSSException, ClientException;
AccessControlList getBucketAcl(String var1) throws OSSException, ClientException;
AccessControlList getBucketAcl(GenericRequest var1) throws OSSException, ClientException;
*********
bucket 是否存在
boolean doesBucketExist(String var1) throws OSSException, ClientException;
boolean doesBucketExist(GenericRequest var1) throws OSSException, ClientException;
*********
object 对象
ObjectListing listObjects(String var1) throws OSSException, ClientException;
ObjectListing listObjects(String var1, String var2) throws OSSException, ClientException;
ObjectListing listObjects(ListObjectsRequest var1) throws OSSException, ClientException;
*********
object 存储
PutObjectResult putObject(String var1, String var2, InputStream var3) throws OSSException, ClientException;
PutObjectResult putObject(String var1, String var2, InputStream var3, ObjectMetadata var4) throws OSSException, ClientException;
PutObjectResult putObject(String var1, String var2, File var3, ObjectMetadata var4) throws OSSException, ClientException;
PutObjectResult putObject(String var1, String var2, File var3) throws OSSException, ClientException;
PutObjectResult putObject(PutObjectRequest var1) throws OSSException, ClientException;
PutObjectResult putObject(URL var1, String var2, Map var3) throws OSSException, ClientException;
PutObjectResult putObject(URL var1, String var2, Map var3, boolean var4) throws OSSException, ClientException;
PutObjectResult putObject(URL var1, InputStream var2, long var3, Map var5) throws OSSException, ClientException;
PutObjectResult putObject(URL var1, InputStream var2, long var3, Map var5, boolean var6) throws OSSException, ClientException;
*********
object 追加
AppendObjectResult appendObject(AppendObjectRequest var1) throws OSSException, ClientException;
*********
object 复制
CopyObjectResult copyObject(String var1, String var2, String var3, String var4) throws OSSException, ClientException;
CopyObjectResult copyObject(CopyObjectRequest var1) throws OSSException, ClientException;
*********
object 获取
OSSObject getObject(String var1, String var2) throws OSSException, ClientException;
ObjectMetadata getObject(GetObjectRequest var1, File var2) throws OSSException, ClientException;
OSSObject getObject(GetObjectRequest var1) throws OSSException, ClientException;
OSSObject selectObject(SelectObjectRequest var1) throws OSSException, ClientException;
OSSObject getObject(URL var1, Map var2) throws OSSException, ClientException;
*********
object 删除
VoidResult deleteObject(String var1, String var2) throws OSSException, ClientException;
VoidResult deleteObject(GenericRequest var1) throws OSSException, ClientException;
DeleteObjectsResult deleteObjects(DeleteObjectsRequest var1) throws OSSException, ClientException;
*********
object 是否存在
boolean doesObjectExist(String var1, String var2) throws OSSException, ClientException;
boolean doesObjectExist(GenericRequest var1) throws OSSException, ClientException;
boolean doesObjectExist(String var1, String var2, boolean var3);
boolean doesObjectExist(GenericRequest var1, boolean var2) throws OSSException, ClientException;
*********
object 修复
RestoreObjectResult restoreObject(String var1, String var2) throws OSSException, ClientException;
RestoreObjectResult restoreObject(GenericRequest var1) throws OSSException, ClientException;
RestoreObjectResult restoreObject(String var1, String var2, RestoreConfiguration var3) throws OSSException, ClientException;
RestoreObjectResult restoreObject(RestoreObjectRequest var1) throws OSSException, ClientException;