Skip to content
SNDA Storage Service SDK for Java
Java
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
src
.gitignore
CHANGELOG
README.md
pom.xml

README.md

盛大云存储服务Java SDK

盛大云存储服务Java SDK由盛大官方提供,开发者可以利用该工具包实现:

  1. 管理Bucket信息
  2. 上传与下载Object数据
  3. 生成与设置Bucket Policy
  4. 生成预签名(Presigned)的可公开访问的URL

特点

  1. DSL(Fluent Interface)风格的API,简洁易用
  2. 支持Access Policy Language,通过DSL风格的API生成Bucket Policy
  3. 支持大文件上传(最大5TB),自动通过Multipart Upload机制上传大文件,对开发者透明
  4. 提供了独立的签名与认证模块供开发者使用
  5. 支持HTTPS安全网络访问
  6. 无需配置Endpoint,自动支持多盛大云存储服务的多IDC
  7. 支持限速传输

下载

目前最新的版本是2012年09月24日发布的2.0.0:

  1. snda-cloud-storage-java-sdk-2.0.0.jar 二进制发布包
  2. snda-cloud-storage-java-sdk-2.0.0.zip 包含源代码,第三方依赖,Javadoc等内容的发布包

Maven

<dependency>
    <groupId>com.snda</groupId>
    <artifactId>snda-cloud-storage-java-sdk</artifactId>
    <version>2.0.0</version>
</dependency>

配置Sonatype仓库

<repository>
    <id>sonatype-service</id>
    <url>https://oss.sonatype.org/service/local/repositories/releases/content</url>
</repository>

使用

盛大云存储服务Java SDK提供了DSL风格的Java API,易于上手,简单高效。其核心为SNDAStorage对象,开发者通过该对象提供的多种方法来访问盛大云存储服务。

构建SNDAStorage对象

SNDAStorage storage = new SNDAStorageBuilder().credential(yourAccessKeyId, yourSecretAccessKey).build();

更多的设置:

SNDAStorage storage = new SNDAStorageBuilder().
    credential(yourAccessKeyId, yourSecretAccessKey).
    https().                        //启用HTTPS
    bytesPerSecond(64 * 1024).      //限制每秒传输速率为64KB
    connectionTimeout(10 * 1000).   //设置ConnectionTimeout为10秒
    soTimeout(30 * 1000).           //设置SoTimeout为30秒
    build();

SNDAStorage对象内部维护了一组HTTP连接池,在不使用该对象时,应该调用其destory方法销毁该对象,

storage.destory();

列出所有的Bucket

for (BucketSummary each : storage.listBuckets()) {
    String name = each.getName();
}

Bucket相关操作

在默认的Location节点中创建名为mybucket的Bucket

storage.bucket("mybucket").create();

在华东一节点创建Bucket

storage.bucket("mybucket").location(Location.HUADONG_1).create();

查看Location

storage.bucket("mybucket").location().get();    

删除Bucket

storage.bucket("mybucket").delete();            

设置Bucket Policy

storage.bucket("mybucket").policy(myPolicy).set();

获取Bucket Policy

storage.bucket("mybucket").policy().get();

删除Bucket Policy

storage.bucket("mybucket").policy().delete();   

根据条件列出Objects

ListBucketResult result = storage.              
    bucket("mybucket").
    prefix("upload/").
    delimiter("/").
    maxKeys(25).
    listObjects();                                  

根据条件列出Multipart Uploads

ListMultipartUploadsResult result = storage.    
    bucket("mybucket").
    prefix("data/").
    maxUploads(50).
    listMultipartUploads();                         

Object相关的操作

上传数据

storage.bucket("mybucket").object("data/upload/pic.jpg").entity(new File("d:\\user\\my_picture.jpg")).upload();

自定义Metadata

storage.bucket("mybucket").object("data/upload/mydata").
    contentType("application/octet-stream").    
    contentMD5("ABCDEFGUVWXYZ").
    contentLanguage("en").
    metadata("x-snda-meta-foo", "bar").
    metadata("x-snda-meta-creation", new DateTime()).
    metadata("x-snda-meta-author", "wangzijian@snda.com").
    entity(2048L, inputStream).
    upload();

下载数据

SNDAObject object = null;
try {
    object = storage.bucket("mybucket").object("data/upload/pic.jpg").download();
    read(object.getContent());
} finally {
    Closeables.closeQuietly(object);
}

SNDAObject实现了java.io.Closeable接口,其内部持有了代表Object内容的InputStream,需要在使用完毕时关闭。

下载至本地硬盘

storage.bucket("mybucket").object("data/pic.jpg").download().to(new File("~/download/my_pic.jpg"));

条件下载(Conditional GET)

storage.bucket("mybucket").object("norther.mp3").ifModifedSince(new DateTime(2012, 10, 7, 20, 0, 0)).download();

分段下载(Range GET)

storage.bucket("mybucket").object("norther.mp3").range(1000, 5000).download();

获取Object信息与Metadata(HEAD Object)

SNDAObjectMetadata metadata = storage.bucket("mybucket").object("music/norther.mp3").head();

更新Object信息与Metadata

storage.bucket("mybucket").object("music/norther.mp3").
    contentType("audio/mpeg").
    metadata("x-snda-meta-nation", "Finland").
    update();

复制Object

storage.bucket("mybucket").object("book/english.txt").
    copySource("otherbucket", "data/edu/main.txt");
    replaceMetadata().
    contentType("text/plain").
    metadata("x-snda-meta-author", "Jack Jackson").
    copy();

Bucket Policy

盛大云存储SDK提供了强大的Bucket Policy构建器,开发者可以轻易生成和设置所需要的Bucket Policy。

加入静态引入

import static com.snda.storage.policy.fluent.impl.Conditions.*

允许匿名用户下载该Bucket中key以public作为前缀的所有Object,同时限定User-Agent为Android或IOS,防盗链Referer设置为.mycompany.com/

Statement statement = Statement.allow().anyone().perform("storage:GetObject").to("srn:snda:storage:::mybucket/public/*").
    where(userAgent().equals("Android", "IOS")).
    and(referer().equals("*.mycompany.com/*")).
    identifed("public-get-object");

storage.bucket("mybucket").policy(new Policy().
    withRandomId().
    withStatement(statement)).
    set();

允许匿名用户通过HTTPS下载该Bucket中的所有Object,且请求时间必须在2012年10月1日0点至2012年10月8日0点之间:

Statement.allow().anyone().perform("storage:GetObject").to("srn:snda:storage:::mybucket/*").
    where(secureTransport().bool(true)).
    and(currentTime().greaterThan(new DateTime(2012, 10, 1, 0, 0, 0))).
    and(currentTime().lessThan(new DateTime(2012, 10, 8, 0, 0, 0))).
    identifed("public-get-object-with-time-restriction");

设置请求的IP必须在指定的"192.168.176.0/24"范围内:

Statement.allow().anyone().perform("storage:GetObject").to("srn:snda:storage:::mybucket/*").
    where(sourceIp().ipAddress("192.168.176.0/24")).
    identifed("public-get-object-with-connection-restriction");

生成预签名的URI

盛大云存储提供了一种基于查询字串(Query String)的认证方式,即通过预签名(Presigned)的方式,为要发布的Object生成一个带有认证信息的URI,并将它分发给第三方用户来实现公开访问。

SDK中提供了PresigendURIBuilder来构造预签名URI。

URI uri = storage.presignedURIBuilder().
    bucket("mybucket").
    key("hello_world.mp4").
    expires(new DateTime().plusMinutes(5))
    build();

生成的URI如下:

http://storage-huadong-1.sdcloud.cn/mybucket/hello_world.mp4?Expires=1348044780&SNDAAccessKeyId=norther&Signature=SJawXv5QdQHcFrTqnx3RpmTN9WI%3D

Entity

Entity代表要上传的Object的内容,由内容与长度组成,接口定义如下:

public interface Entity extends InputSupplier<InputStream> {

    long getContentLength();

    InputStream getInput() throws IOException;
}

getContentLength方法返回该Entity的长度,盛大云存储服务要求上传的数据必须事先指定其长度,最大不得超过5TB。

getInput方法继承自Google Guava的InputSupplier。 InputSupplier代表Entity的内容,是一个打开InputStream的回调(Callback)。 在云存储SDK的不同模块之间,我们只传递InputSupplier的引用,而不是直接传递InputStream。 这是一种高效并且灵活的使用流的方式,因为只有在必要的时候,应用才会调用InputSupplier的getInput方法来打开一个新的InputStream,并保证该InputStream在使用完毕时能被正确的关闭。

下面的样例中,盛大云存储SDK只在必须要的情况下,才会调用getInput来打开流。

object.bucket("mybucket").object("key").
    contentType("video/mp4").
    entity(65535, new InputSupplier<InputStream>() {
        @Override
        public InputStream getInput() throws IOException {
            return openStream();
        }
    }).
    upload();

云存储SDK提供了3种默认的Entity实现,包括InputSupplierEntity, InputStreamEntity,与 FileEntity

参考FileEntity的实现:

public class FileEntity implements Entity {

    private final File file;

    public FileEntity(File file) {
        this.file = checkNotNull(file);
    }

    @Override
    public long getContentLength() {
        return file.length();
    }

    @Override
    public InputStream getInput() throws IOException {
        return new FileInputStream(file);
    }
}

注意 InputStreamEntity并不关闭其持有的InputStream对象,这样的做法符合IO Stream使用的最佳实现,即:关闭自己打开的流

样例如下:

InputStream inputStream = null;
try {
    inputStream = openInputStream(); //用户应负责关闭自己所打开的流,盛大云存储SDK并不会关闭用户传入的InputStream对象
    storage.bucket("mybucket").object("key").entity(256, inputStream).upload();
} finally {
    Closeables.closeQuietly(inputStream);
}

Multipart Upload API

开发这使用盛大云存储SDK上传文件时,SDK会透明的使用Multipart Upload实现对大文件上传,一般情况下用户不需要自己来使用Multipart Upload API。

若开发者有自己使用Multipart Upload的需求,可以参看下面的使用样例:

初始化Multipart Upload

InitiateMultipartUploadResult result = storage.bucket("mybucket").object("blob").initiateMultipartUpload();

获得Multipart Upload Id

String uploadId = result.getUploadId();             

上传Part

storage.bucket("mybucket").object("blob").multipartUpload(uploadId).
    partNumber(1).
    entity(new File("/user/data/bin1")).
    upload();

复制Part

storage.bucket("mybucket").object("blob").multipartUpload(uploadId).
    partNumber(2).
    copySource("otherbucket", "bigdata").
    copySourceRange(255, 65335);
    copy();

完成Multipart Upload

storage.bucket("mybucket").object("blob").multipartUpload(uploadId).
    part(1, "ETag1").
    part(2, "ETag2").
    complete();

放弃Multipart Upload

storage.bucket("mybucket").object("blob").multipartUpload(uploadId).abort();

列出未完成的Parts

storage.bucket("mybucket").object("blob").multipartUpload(uploadId).
    partNumberMarker(10).
    maxParts(5).
    listParts();

Exception

盛大云存储SDK会将云存储服务返回的Error转换成统一的异常层次:SNDAServiceException,用户可以基于该类型来实现诸如错误处理与诊断等操作。

public class SNDAServiceException extends RuntimeException {

    public int status()             //获得错误代表的HTTP状态码(Status)

    public String getRequestId()    //获得请求的ID,当错误发生时,开发者可以将该ID记录下来并告知盛大云存储服务来快速诊断错误

    public DateTime getDate()       //获得异常发生的时间

    public String getCode()         //获得错误码,对应Error结构中的Code元素,HEAD请求时,该值为null

    public String getResource()     //获得错误对应的资源,对应Error结构中的Resource元素,HEAD请求时,该值为null

    public String getErrorMessage() //获得错误消息,对应Error结构中的Message元素,HEAD请求时,该值为null

}

除了标准的错误信息外,用户还可以获得额外的错误信息:

try {
    doSomething();
} catch (SNDAServiceException e) {
    if ("SignatureDoesNotMatch".equals(e.getCode()) {
        String signatureProvided = e.getError().get("SignatureProvided");
    }
}

依赖

盛大云存储SDK依赖以下的第三方库:

依赖 描述 网址
Google Guava Google提供的Java基础类库,提供了函数式编程,并发,集合操作等多种基础功能 http://code.google.com/p/guava-libraries/
Joda Time 一套关于时间的类库,已被收入至JDK 7中 http://joda-time.sourceforge.net/
SLF4J 功能强大的日志框架 http://www.slf4j.org/
Apache Commons-Lang 用来实现一些基础的操作,例如Object hashcode与equals方法的实现 http://commons.apache.org/lang/
Apache Commons-Codec 用来进行一些诸如Base64之类的编码算法 http://commons.apache.org/codec/
Apache HTTP Client 用来实现HTTP协议与网络数据的传输 http://hc.apache.org/httpclient-3.x/
Jackson 著名的JSON格式序列化工具,只有在使用Bucket Policy时需要 http://jackson.codehaus.org/

Copyright

Copyright (c) 2012 grandcloud.cn. All rights reserved.

Something went wrong with that request. Please try again.