一、资料链接
二、入门demo 下载地址
public class HelloOSS {
static Logger logger = Logger.getLogger(HelloOSS.class);
// endpoint是访问OSS的域名。如果您已经在OSS的控制台上 创建了Bucket,请在控制台上查看域名。
// 如果您还没有创建Bucket,endpoint选择请参看文档中心的“开发人员指南 > 基本概念 > 访问域名”,
// 链接地址是:https://help.aliyun.com/document_detail/oss/user_guide/oss_concept/endpoint.html?spm=5176.docoss/user_guide/endpoint_region
// endpoint的格式形如“http://oss-cn-hangzhou.aliyuncs.com/”,注意http://后不带bucket名称,
// 比如“http://bucket-name.oss-cn-hangzhou.aliyuncs.com”,是错误的endpoint,请去掉其中的“bucket-name”。
private static String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// accessKeyId和accessKeySecret是OSS的访问密钥,您可以在控制台上创建和查看,
// 创建和查看访问密钥的链接地址是:https://ak-console.aliyun.com/#/。
// 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
// Bucket用来管理所存储Object的存储空间,详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
// Bucket命名规范如下:只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
private static String bucketName = "<yourBucketName>";
// Object是OSS存储数据的基本单元,称为OSS的对象,也被称为OSS的文件。详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
// Object命名规范如下:使用UTF-8编码,长度必须在1-1023字节之间,不能以“/”或者“\”字符开头。
private static String firstKey = "my-first-key";
public static void main(String[] args) {
// 日志配置,OSS Java SDK使用log4j记录错误信息。示例程序会在工程目录下生成“oss-demo.log”日志文件,默认日志级别是INFO。
// 日志的配置文件是“conf/log4j.properties”,如果您不需要日志,可以没有日志配置文件和下面的日志配置。
PropertyConfigurator.configure("conf/log4j.properties");
logger.info("Started");
// 生成OSSClient,您可以指定一些参数,详见“SDK手册 > Java-SDK > 初始化”,
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/init.html?spm=5176.docoss/sdk/java-sdk/get-start
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
try {
// 判断Bucket是否存在。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
if (ossClient.doesBucketExist(bucketName)) {
System.out.println("您已经创建Bucket:" + bucketName + "。");
} else {
System.out.println("您的Bucket不存在,创建Bucket:" + bucketName + "。");
// 创建Bucket。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
ossClient.createBucket(bucketName);
}
// 查看Bucket信息。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
BucketInfo info = ossClient.getBucketInfo(bucketName);
System.out.println("Bucket " + bucketName + "的信息如下:");
System.out.println("\t数据中心:" + info.getBucket().getLocation());
System.out.println("\t创建时间:" + info.getBucket().getCreationDate());
System.out.println("\t用户标志:" + info.getBucket().getOwner());
// 把字符串存入OSS,Object的名称为firstKey。详细请参看“SDK手册 > Java-SDK > 上传文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/upload_object.html?spm=5176.docoss/user_guide/upload_object
InputStream is = new ByteArrayInputStream("Hello OSS".getBytes());
ossClient.putObject(bucketName, firstKey, is);
System.out.println("Object:" + firstKey + "存入OSS成功。");
// 下载文件。详细请参看“SDK手册 > Java-SDK > 下载文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/download_object.html?spm=5176.docoss/sdk/java-sdk/manage_object
OSSObject ossObject = ossClient.getObject(bucketName, firstKey);
InputStream inputStream = ossObject.getObjectContent();
StringBuilder objectContent = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
while (true) {
String line = reader.readLine();
if (line == null)
break;
objectContent.append(line);
}
inputStream.close();
System.out.println("Object:" + firstKey + "的内容是:" + objectContent);
// 文件存储入OSS,Object的名称为fileKey。详细请参看“SDK手册 > Java-SDK > 上传文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/upload_object.html?spm=5176.docoss/user_guide/upload_object
String fileKey = "README.md";
ossClient.putObject(bucketName, fileKey, new File("README.md"));
System.out.println("Object:" + fileKey + "存入OSS成功。");
// 查看Bucket中的Object。详细请参看“SDK手册 > Java-SDK > 管理文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_object.html?spm=5176.docoss/sdk/java-sdk/manage_bucket
ObjectListing objectListing = ossClient.listObjects(bucketName);
List<OSSObjectSummary> objectSummary = objectListing.getObjectSummaries();
System.out.println("您有以下Object:");
for (OSSObjectSummary object : objectSummary) {
System.out.println("\t" + object.getKey());
}
// 删除Object。详细请参看“SDK手册 > Java-SDK > 管理文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_object.html?spm=5176.docoss/sdk/java-sdk/manage_bucket
ossClient.deleteObject(bucketName, firstKey);
System.out.println("删除Object:" + firstKey + "成功。");
ossClient.deleteObject(bucketName, fileKey);
System.out.println("删除Object:" + fileKey + "成功。");
} catch (OSSException oe) {
oe.printStackTrace();
} catch (ClientException ce) {
ce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
ossClient.shutdown();
}
logger.info("Completed");
}
}
三、oss基础学习
这个demo是阿里云官方提供的demo,那么我们开始一步步分析下他的代码。来帮助我们更好的学习sso。
3.1 创建
首先从创建 OSSClient 开始,点进源码,可以发现创建ossClient有多种创建方式。
public class OSSClient implements OSS {
private CredentialsProvider credsProvider;
private URI endpoint;
private ServiceClient serviceClient;
private OSSBucketOperation bucketOperation;
private OSSObjectOperation objectOperation;
private OSSMultipartOperation multipartOperation;
private CORSOperation corsOperation;
private OSSUploadOperation uploadOperation;
private OSSDownloadOperation downloadOperation;
private LiveChannelOperation liveChannelOperation;
private OSSUdfOperation udfOperation;
/** @deprecated 域名默认指向华东地区的(杭州) */
@Deprecated
public OSSClient(String accessKeyId, String secretAccessKey) {
this("http://oss.aliyuncs.com", (CredentialsProvider)(new DefaultCredentialProvider(accessKeyId, secretAccessKey)));
}
public OSSClient(String endpoint, String accessKeyId, String secretAccessKey) {
this(endpoint, (CredentialsProvider)(new DefaultCredentialProvider(accessKeyId, secretAccessKey)), (ClientConfiguration)null);
}
// 暂时还不知道,看名字定义估计是传入一个token来进行安全认证的
public OSSClient(String endpoint, String accessKeyId, String secretAccessKey, String securityToken) {
this(endpoint, (CredentialsProvider)(new DefaultCredentialProvider(accessKeyId, secretAccessKey, securityToken)), (ClientConfiguration)null);
}
// 需要传入ClientConfiguration配置文件,可配置代理、连接超时、最大连接数等参数。
public OSSClient(String endpoint, String accessKeyId, String secretAccessKey, ClientConfiguration config) {
this(endpoint, (CredentialsProvider)(new DefaultCredentialProvider(accessKeyId, secretAccessKey)), (ClientConfiguration)config);
}
public OSSClient(String endpoint, String accessKeyId, String secretAccessKey, String securityToken, ClientConfiguration config) {
this(endpoint, (CredentialsProvider)(new DefaultCredentialProvider(accessKeyId, secretAccessKey, securityToken)), (ClientConfiguration)config);
}
public OSSClient(String endpoint, CredentialsProvider credsProvider) {
this(endpoint, (CredentialsProvider)credsProvider, (ClientConfiguration)null);
}
public OSSClient(String endpoint, CredentialsProvider credsProvider, ClientConfiguration config) {
this.credsProvider = credsProvider;
config = config == null ? new ClientConfiguration() : config;
if (config.isRequestTimeoutEnabled()) {
this.serviceClient = new TimeoutServiceClient(config);
} else {
this.serviceClient = new DefaultServiceClient(config);
}
this.initOperations();
this.setEndpoint(endpoint);
}
创建完ossClient之后就需要创建存储空间了。毕竟我们的object都是存放到存储空间中的。
使用ossClient创建存储空间的方法有两种
/**
* 直接命名存储空间的name来创建
**/
public Bucket createBucket(String bucketName) throws OSSException, ClientException {
return this.createBucket(new CreateBucketRequest(bucketName));
}
/**
* 如果创建存储空间的同时需要指定存储类型以及数据容灾类型
* 则需要 CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
* 然后传入createBucketRequest 来创建
**/
public Bucket createBucket(CreateBucketRequest createBucketRequest) throws OSSException, ClientException {
return this.bucketOperation.createBucket(createBucketRequest);
}
3.2 文件上传
接下来就是基础的操作了----上传文件
阿里云将上传文件分为五大类:简单上传、表单上传、追加上传、断点断传上传、分片上传。
简单上传其实就是上传单个文件,分为流式上传和文件上传。
// 创建OSSClient实例。
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 上传字符串。
{
// 创建PutObjectRequest对象。
String content = "Hello OSS";
// <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
PutObjectRequest putObjectRequest = new PutObjectRequest("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content.getBytes()));
ossClient.putObject(putObjectRequest);
}
// 上传Byte数组。
{
byte[] content = "Hello OSS".getBytes();
ossClient.putObject("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content));
}
// 上传网络流。
{
InputStream inputStream = new URL("https://www.aliyun.com/").openStream();
ossClient.putObject("<yourBucketName>", "<yourObjectName>", inputStream);
}
// 上传文件流。
{
InputStream inputStream = new FileInputStream("<yourlocalFile>");
ossClient.putObject("<yourBucketName>", "<yourObjectName>", inputStream);
}
// 上传文件
{
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest("<yourBucketName>", "<yourObjectName>", new File("<yourLocalFile>"));
ossClient.putObject(putObjectRequest);
}
从代码中可以看出,简单上传主要就是上传InputStream或PutObjectRequest对象。
表单上传:
表单上传是直接将表单内容传到阿里云oss存储服务器中。(划重点)
public class PostObjectSample {
// 上传文件
private String localFilePath = "<yourLocalFile>";
// Endpoint以杭州为例,其它Region请按实际情况填写。
private String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
private String accessKeyId = "<yourAccessKeyId>";
private String accessKeySecret = "<yourAccessKeySecret>";
// 存储空间名称
private String bucketName = "<yourBucketName>";
// 文件名称
private String objectName = "<yourObjectName>";
/**
* 表单上传
* @throws Exception
*/
private void PostObject() throws Exception {
// 在URL中添加存储空间名称,添加后URL如下:http://yourBucketName.oss-cn-hangzhou.aliyuncs.com
String urlStr = endpoint.replace("http://", "http://" + bucketName+ ".");
// 表单Map。
Map<String, String> formFields = new LinkedHashMap<String, String>();
// 设置文件名称。
formFields.put("key", this.objectName);
// 设置Content-Disposition。
formFields.put("Content-Disposition", "attachment;filename="
+ localFilePath);
// 设置回调参数。
Callback callback = new Callback();
// 设置回调服务器地址,如http://oss-demo.aliyuncs.com:23450或http://127.0.0.1:9090。
callback.setCallbackUrl("<yourCallbackServerUrl>");
// 设置回调请求消息头中Host的值,如oss-cn-hangzhou.aliyuncs.com。
callback.setCallbackHost("<yourCallbackServerHost>");
// 设置发起回调时请求body的值。
callback.setCallbackBody("{\\\"mimeType\\\":${mimeType},\\\"size\\\":${size}}");
// 设置发起回调请求的Content-Type。
callback.setCalbackBodyType(CalbackBodyType.JSON);
// 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始,且必须为小写。
callback.addCallbackVar("x:var1", "value1");
callback.addCallbackVar("x:var2", "value2");
// 在表单Map中设置回调参数。
setCallBack(formFields, callback);
// 设置OSSAccessKeyId。
formFields.put("OSSAccessKeyId", accessKeyId);
String policy = "{\"expiration\": \"2120-01-01T12:00:00.000Z\",\"conditions\": [[\"content-length-range\", 0, 104857600]]}";
String encodePolicy = new String(Base64.encodeBase64(policy.getBytes()));
// 设置policy。
formFields.put("policy", encodePolicy);
// 生成签名。
String signaturecom = com.aliyun.oss.common.auth.ServiceSignature.create().computeSignature(accessKeySecret, encodePolicy);
// 设置签名。
formFields.put("Signature", signaturecom);
String ret = formUpload(urlStr, formFields, localFilePath);
System.out.println("Post Object [" + this.objectName + "] to bucket [" + bucketName + "]");
System.out.println("post reponse:" + ret);
}
private static String formUpload(String urlStr, Map<String, String> formFields, String localFile)
throws Exception {
String res = "";
HttpURLConnection conn = null;
String boundary = "9431149156168";
try {
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(30000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
// 设置MD5值。MD5值是由整个body计算得出的。
conn.setRequestProperty("Content-MD5", "<yourContentMD5>");
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
OutputStream out = new DataOutputStream(conn.getOutputStream());
// 遍历读取表单Map中的数据,将数据写入到输出流中。
if (formFields != null) {
StringBuffer strBuf = new StringBuffer();
Iterator<Entry<String, String>> iter = formFields.entrySet().iterator();
int i = 0;
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
String inputName = entry.getKey();
String inputValue = entry.getValue();
if (inputValue == null) {
continue;
}
if (i == 0) {
strBuf.append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
+ inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
} else {
strBuf.append("\r\n").append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
+ inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
}
i++;
}
out.write(strBuf.toString().getBytes());
}
// 读取文件信息,将要上传的文件写入到输出流中。
File file = new File(localFile);
String filename = file.getName();
String contentType = new MimetypesFileTypeMap().getContentType(file);
if (contentType == null || contentType.equals("")) {
contentType = "application/octet-stream";
}
StringBuffer strBuf = new StringBuffer();
strBuf.append("\r\n").append("--").append(boundary)
.append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\"file\"; "
+ "filename=\"" + filename + "\"\r\n");
strBuf.append("Content-Type: " + contentType + "\r\n\r\n");
out.write(strBuf.toString().getBytes());
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
in.close();
byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes();
out.write(endData);
out.flush();
out.close();
// 读取返回数据。
strBuf = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
strBuf.append(line).append("\n");
}
res = strBuf.toString();
reader.close();
reader = null;
} catch (Exception e) {
System.err.println("Send post request exception: " + e);
throw e;
} finally {
if (conn != null) {
conn.disconnect();
conn = null;
}
}
return res;
}
private static void setCallBack(Map<String, String> formFields, Callback callback) {
if (callback != null) {
String jsonCb = OSSUtils.jsonizeCallback(callback);
String base64Cb = BinaryUtil.toBase64String(jsonCb.getBytes());
formFields.put("callback", base64Cb);
if (callback.hasCallbackVar()) {
Map<String, String> varMap = callback.getCallbackVar();
for (Entry<String, String> entry : varMap.entrySet()) {
formFields.put(entry.getKey(), entry.getValue());
}
}
}
}
public static void main(String[] args) throws Exception {
PostObjectSample ossPostObject = new PostObjectSample();
ossPostObject.PostObject();
}
}
追加上传
简单上传,表单上传,断点续传上传等,创建的Object都是Normal类型,这种Object在上传结束之后内容就是固定的,只能读取,不能修改。如果Object内容发生了改变,只能重新上传同名的Object来覆盖之前的内容。而追加上传(Append Object),是在一个Object后面直接追加内容。通过这种方式操作的Object的类型为Appendable Object,
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String content1 = "Hello OSS A \n";
String content2 = "Hello OSS B \n";
String content3 = "Hello OSS C \n";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。
meta.setContentType("text/plain");
// 通过AppendObjectRequest设置多个参数。
AppendObjectRequest appendObjectRequest = new AppendObjectRequest("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content1.getBytes()),meta);
// 通过AppendObjectRequest设置单个参数。
// 设置存储空间名称。
//appendObjectRequest.setBucketName("<yourBucketName>");
// 设置文件名称。
//appendObjectRequest.setKey("<yourObjectName>");
// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为InputStream类型。
//appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为File类型。
//appendObjectRequest.setFile(new File("<yourLocalFile>"));
// 指定文件的元信息,第一次追加时有效。
//appendObjectRequest.setMetadata(meta);
// 第一次追加。
// 设置文件的追加位置。
appendObjectRequest.setPosition(0L);
AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 文件的64位CRC值。此值根据ECMA-182标准计算得出。
System.out.println(appendObjectResult.getObjectCRC());
// 第二次追加。
// nextPosition指明下一次请求中应当提供的Position,即文件当前的长度。
appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 第三次追加。
appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 关闭OSSClient。
ossClient.shutdown();
断点上传和分片上传:
将要上传的文件分成若干个分片(Part)分别上传,所有分片都上传完成后,将所有分片合并成完整的文件,完成整个文件的上传。
适用场景:恶劣的网络环境(如手机端)、加速上传(需要上传的文件很大时)、流式上传(不确定上传的文件大小时)
PS:大小限制:在这种上传方式下,Object的大小是由Part来决定的,最大支持10000块Part。每块Part最小100KB(最后一块可以比100KB小),最大5GB。Object的大小不能超过48.8TB。
其他上传方式单个文件不能超过5gb。
授权给第三方上传:
就是上传时将文件直接上传给oss存储而不是服务器。