友盟+搜索

{{errorMsg}}

开通服务

开通服务,创建空间用于文件存储,参考 接入指引

获取 SDK

通过Maven方式引入

Maven 配置如下:

<!-- TAE Nexus服务器 -->
<repositories>
  <repository>
    <id>taerepository</id>
    <url>http://mvnrepo.tae.taobao.com/content/groups/public/</url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
  <repository>
    <id>taesnapshots</id> 
    <url>http://mvnrepo.tae.taobao.com/content/repositories/snapshots/ </url>
    <releases>
      <enabled>false</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
    </snapshots>
  </repository>
  <repository>
    <id>taereleases</id> 
    <url>http://mvnrepo.tae.taobao.com/content/repositories/releases/ </url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>

<!-- 顽兔多媒体 SDK -->
<dependency>
  <groupId>com.alibaba.media</groupId>
  <artifactId>sdk</artifactId>
  <version>1.1.0</version>
</dependency>

直接下载

通过 控制台 进入 SDK 下载页面,直接下载 Java SDK

运行 Demo

DEMO 下载

点击下载

如何运行

分别在 MediaClientDemo、ManagerClientDemo、UploadClientDemo 三个类的初始化配置中,填入开发者自己的AK、SK 和 namespace后,直接运行main函数即可。示例如下:

如何获取 AK 和 SK? 进入控制台 操作路径为:我的百川 -> 百川秘钥,如图示:

SDK 基本接口

鉴权接口

作用:

根据上传策略生成上传Token,一般用于鉴权服务器

类:

UploadTokenClient

接口描述:

// 通过上传策略获取上传Token
String getUploadToken(UploadPolicy uploadPolicy) throws MediaException;

示例代码

// 1. 定义全局配置信息
MediaConfiguration configuration = new MediaConfiguration();
configuration.setType(MediaConfiguration.TYPE_TOP);
configuration.setAk("<AccessKey>");
configuration.setSk("<AccessSecret>");
configuration.setNamespace("<namespace>");

// 2. 获取鉴权Client
UploadTokenClient tokenClient = new DefaultUploadTokenClient(configuration);

// 3. 定义上传策略
UploadPolicy uploadPolicy = new UploadPolicy();
uploadPolicy.setInsertOnly(UploadPolicy.INSERT_ONLY_NONE);
uploadPolicy.setExpiration(System.currentTimeMillis() + 3600 * 1000);

// 4. 获取上传Token
String token = tokenClient.getUploadToken(uploadPolicy);

上传接口

作用:

用于服务端文件上传

类:

MediaClient 和 UploadClient,其中 UploadClient 提供了所有上传选择,可满足个性化上传需求;MediaClient 继承了 UploadClient,同时提供了两个极简的上传接口,可以直接传入本地文件或输入流,更容易上手。

接口描述

// 简单上传接口,直接传入本地文件
Result<MediaFile> upload(String dir, String name, File file);

// 简单上传接口,直接传入输入流
Result<MediaFile> upload(String dir, String name, InputStream input, long size);

// 直接上传接口,满足个性化上传需求
Result<UploadResponse> upload(UploadRequest req);

// 分片上传初始化接口,返回的UploadId是分片标记
Result<MultipartInitResponse> multipartInit(MultipartInitRequest req);

// 分片上传接口,除最后一片外其他片大小不能小于100Kb
Result<MultipartUploadResponse> multipartUpload(MultipartUploadRequest req);

// 分片上传完成接口,将所有分片组织为一个文件
Result<MultipartCompleteResponse> multipartComplete(MultipartCompleteRequest req);

// 分片上传取消接口,调用该接口后会清理已上传的分片
Result<Void> multipartCancel(MultipartCancelRequest req);

示例代码

// 0.1 定义全局配置信息
MediaConfiguration configuration = new MediaConfiguration();
configuration.setType(MediaConfiguration.TYPE_TOP);
configuration.setAk("<AccessKey>");
configuration.setSk("<AccessSecret>");
configuration.setNamespace("<namespace>");

// 0.2 获取Client
MediaClient client = new DefaultMediaClient(configuration);

// 0.3 待上传的文件
File file = new File("图片所在路径");
File bigFile = new File("图片所在路径");

// 0.4 自定义上传策略
UploadPolicy uploadPolicy = new UploadPolicy();
uploadPolicy.setInsertOnly(UploadPolicy.INSERT_ONLY_NONE);
uploadPolicy.setExpiration(System.currentTimeMillis() + 3600 * 1000);


// 1. 简单上传接口,直接上传文件
Result<MediaFile> result = client.upload("保存路径", 保存文件名称", file);

// 2. 直接上传接口,满足个性化上传需求
UploadRequest uploadRequest = new UploadRequest(uploadPolicy);
uploadRequest.setFile(file);
uploadRequest.setDir("保存路径");
uploadRequest.setName("保存文件名称");

Result<UploadResponse> result = client.upload(uploadRequest);

// 3. 分片上传,用于大文件上传

int partCount = (int) ((bigFile.length() - 1) / PART_SIZE + 1);
if (partCount <= 1) {
    throw new IllegalArgumentException("at least two pieces of block." + PART_SIZE);
}

// 3.1 初始化分片上传
InputStream in = new FileInputStream(bigFile);
List<MultipartCompleteRequest.PartInfo> parts = new ArrayList<MultipartCompleteRequest.PartInfo>();
MultipartInitRequest initRequest = new MultipartInitRequest(uploadPolicy);
initRequest.setDir("dir");
initRequest.setName("block");
initRequest.setContentSize(PART_SIZE);
initRequest.setContent(in);
Result<MultipartInitResponse> multipartInitResult = client.multipartInit(initRequest);
in.close();

if (!multipartInitResult.isSuccess()) {
    // 初始化分片上传失败,直接退出
    return;
}

parts.add(new MultipartCompleteRequest.PartInfo(multipartInitResult.getData().getPartNumber(), multipartInitResult.getData().geteTag()));

// 3.2 分片上传剩余分片
for (int i = 1; i < partCount; i++) {
    long start = PART_SIZE * i;
    long curPartSize = PART_SIZE < contentFile.length() - start ? PART_SIZE : contentFile.length() - start;
    in = new FileInputStream(contentFile);
    in.skip(start);
    MultipartUploadRequest uploadRequest = new MultipartUploadRequest(uploadPolicy);
    uploadRequest.setDir(multipartInitResult.getData().getDir());
    uploadRequest.setName(multipartInitResult.getData().getName());
    uploadRequest.setContentSize(curPartSize);
    uploadRequest.setId(multipartInitResult.getData().getId());
    uploadRequest.setUploadId(multipartInitResult.getData().getUploadId());
    uploadRequest.setPartNumber(i + 1);
    uploadRequest.setContent(in);
    Result<MultipartUploadResponse> uploadResult = client.multipartUpload(uploadRequest);
    in.close();
    if (!uploadResult.isSuccess()) {
        // 某个分片上传失败
        return;
    }

    parts.add(new MultipartCompleteRequest.PartInfo(uploadResult.getData().getPartNumber(), uploadResult.getData().geteTag()));
}

// 3.3 分支一:完成分片上传
MultipartCompleteRequest completeRequest = new MultipartCompleteRequest(uploadPolicy);
completeRequest.setDir(multipartInitResult.getData().getDir());
completeRequest.setName(multipartInitResult.getData().getName());
completeRequest.setId(multipartInitResult.getData().getId());
completeRequest.setUploadId(multipartInitResult.getData().getUploadId());
completeRequest.setParts(parts);
Result<MultipartCompleteResponse> completeResult = client.multipartComplete(completeRequest);
if (!completeResult.isSuccess()) {
    // 完成分片接口调用失败,打印错误信息
    System.out.println(JSON.toJSONString(completeResult));
}


// 3.3 分支二:取消分片上传
MultipartCancelRequest cancelResult = new MultipartCancelRequest(uploadPolicy);
cancelResult.setDir(multipartInitResult.getData().getDir());
cancelResult.setName(multipartInitResult.getData().getName());
cancelResult.setId(multipartInitResult.getData().getId());
cancelResult.setUploadId(multipartInitResult.getData().getUploadId());
client.multipartCancel(cancelResult);

管理接口

作用

用于文件管理,出于安全性考虑,文件管理只在服务端完成,所以只提供服务端接口

ManageClient

接口描述

// 检查文件是否存在
Result<Boolean> existsFile(String dir, String name);

// 遍历某一目录下的文件
Result<PagedList<MediaFile>> listFiles(String dir, int page, int pageSize);

// 获取文件信息
Result<MediaFile> getFile(String dir, String name);

// 删除文件
Result<Void> deleteFile(String dir, String name);

// 创建目录
Result<Void> createDir(String dir);

// 目录是否存在
Result<Boolean> existsDir(String dir);

// 遍历目录
Result<PagedList<MediaDir>> listDirs(String dir, int page, int pageSize);

// 删除目录
Result<Void> deleteDir(String dir);

示例代码

// 0.1 定义全局配置信息
MediaConfiguration configuration = new MediaConfiguration();
configuration.setType(MediaConfiguration.TYPE_TOP);
configuration.setAk("<AccessKey>");
configuration.setSk("<AccessSecret>");
configuration.setNamespace("<namespace>");

// 0.2 获取Client
MediaClient tokenClient = new DefaultMediaClient(configuration);

// 1. 判断文件是否存在
Result<Boolean> fileExistsResult = client.existsFile("/tmp", "image.jpg");
if (fileExistsResult.isSuccess()) {
    //do something
    System.out.println(fileExistsResult.getData());
} else {
    System.out.println(fileExistsResult.toString());
}

// 2. 获得文件元信息
Result<MediaFile> mediaFileResult = client.getFile("/tmp", "image.jpg");
if (mediaFileResult.isSuccess()) {
    System.out.println(JSON.toJSONString(mediaFileResult.getData()));
} else {
    System.out.println(mediaFileResult);
}

// 3. 分页获取指定目录下的图片元信息
Result<PagedList<MediaFile>> listFilesResult = client.listFiles("/tmp", 1, 10);
if (listFilesResult.isSuccess()) {
    for (MediaFile file : listFilesResult.getData()) {
        System.out.println(JSON.toJSONString(file));
    }
} else { // 调用出错
    System.out.println(listFilesResult.toString());
}

// 4. 删除图片文件
Result<Void> deleteResult = client.deleteFile("/tmp", "image.jpg");
if (deleteResult.isSuccess()) { //删除成功
    System.out.println("Delete File Success");
} else {
    System.out.println(deleteResult.toString());
}


// 5. 创建目录
Result<Void> createDirResult = client.createDir("/tmp/dir");
if (createDirResult.isSuccess()) { // 创建成功
    System.out.println("Create Dir Success");
} else {
    System.out.println(createDirResult.toString());
}

// 6. 判断目录是否存在
Result<Boolean> dirExistsResult = client.existsDir("/tmp/dir");
if (dirExistsResult.isSuccess()) { // 目录是否存在
    System.out.println(dirExistsResult.getData());
} else { // 调用出错
    System.out.println(dirExistsResult.toString());
}

// 7. 分页获取指定文件夹下的目录
Result<PagedList<MediaDir>> mediaDirsResult = client.listDirs("/tmp", 1, 10);
if (mediaDirsResult.isSuccess()) { // 遍历获取到的目录
    for (MediaDir dir : mediaDirsResult.getData()) {
        System.out.println(JSON.toJSONString(dir));
    }
} else { // 调用出错
    System.out.println(mediaDirsResult.toString());
}

SDK 高级用法

Form 表单上传

使用说明

Form表单上传一般用于开发者直接在网页端(通过js)将文件上传至顽兔的情况;向顽兔上传文件必须提供上传 Token,而上传 Token 又是通过服务端后台代码生成的,所以Form表单上传应包含两段代码:

示例代码

// 网页代码
<html>
    <body>
        <form  method="post" action="http://upload.media.aliyun.com/api/proxy/upload?opt=n" enctype="multipart/form-data">
            <label for="file">Filename:</label>
            <input type="file" name="content" />
            <label for="size">size:</label>
            <input type="text" name="size" value="33352"/>
            <label for="filename">filename:</label>
            <input type="text" name="name" value="filename"/>
            <label for="dir">dir:</label>
            <input type="text" name="dir" value="/test" />
            <label for="Authorization">Authorization:</label>
            <input type="text" name="Authorization" value="<%=TOKEN %>"/>
            <br />
            <input type="submit" name="submit" value="Submit" />
        </form>
    </body>
</html>

// 生成上传Token的后台代码

// 1. 定义全局配置信息
MediaConfiguration configuration = new MediaConfiguration();
configuration.setType(MediaConfiguration.TYPE_TOP);
configuration.setAk("<AccessKey>");
configuration.setSk("<AccessSecret>");
configuration.setNamespace("<namespace>");

// 2. 获取鉴权Client
UploadTokenClient tokenClient = new DefaultUploadTokenClient(configuration);

// 3. 定义上传策略
UploadPolicy uploadPolicy = new UploadPolicy();
uploadPolicy.setInsertOnly(UploadPolicy.INSERT_ONLY_NONE);
uploadPolicy.setExpiration(System.currentTimeMillis() + 3600 * 1000);

// 4. 获取上传Token
String token = tokenClient.getUploadToken(uploadPolicy);

上传策略

上传策略旨在帮助开发者更细致的操控上传行为,目前提供的上传策略定义如下:

字段名称

是否必须

说明

dir

指定上传文件的存储路径

如果不指定则会使用接口中传入的dir参数

如果接口中也没有传入dir参数,则默认使用根目录

该参数可以包含占位符

例如:

uploadPolicy.setDir("/${year}/${month}/${day}");

name

指定上传文件的存储文件名

如果不指定则会使用接口中传入的name参数

如果接口中也没有传入name参数,将会抛出异常

该参数可以包含占位符

例如:

uploadPolicy.setName("${hour}-${minute}-${second}.${ext}");

sizeLimit

指定上传文件大小的最大值(单位:字节)

各种资源类型文件大小的系统限制

图片: 10485760 (10Mb: 10 * 1024 * 1024)

默认情况下使用系统限制检查文件大小

mimeLimit

指定上传文件类型的限制(MimeType类型)

允许指定多种类型, 请使用';'隔开

各种资源类型允许上传的MimeType类型

图片:

jpg: image/jpeg

png: image/png

bmp: image/bmp

gif: image/gif

通配符: image/*

callbackUrl

图片上传完成之后,系统回调该Url

callbackHost

在系统回调时,将设置请求头部的Host信息

设置该参数之前应该首先设置callbackUrl

callbackBody

在系统回调时,将设置请求的Body信息

设置该参数之前应该首先设置callbackUrl

该参数可以包含占位符

callbackBodyType

在系统回调时,将设置请求的Body类型

设置该参数之前应该首先设置callbackUrl

设置该参数之前应该首先设置callbackBody

insertOnly

文件上传是否可覆盖

0: 可覆盖, 1: 不可覆盖

默认为可覆盖的模式

detectMime

是否自动检查文件头部信息

0: 不自动检查, 1: 自动检查

默认为自动检查文件头部信息

   returnUrl

上传完成之后,303跳转的Url

returnBody

上传完成之后,返回的Body信息

该参数可以包含占位符

namespace

开发者创建空间时指定的空间唯一标示

expiration

token的过期时间

举例如下:

(System.currentTimeMillis() + 3600 * 1000)

占位符

上传策略中有些策略(例如dir、callbackBody等可以包含类似系统时间、图片长宽、用户自定义变量等),在开发者编写上传策略的时候并不知道具体值,这时,可以通过占位符(${占位符名称})进行表示,顽兔会在运行时进行渲染填充。

例如: 可以在上传策略中指定文件名为 ${year}-${month}-${day}.jpg , 运行时生成的文件名可能就会是这样 2015-2-5.jpg

目前支持的占位符如下列表:

占位符名

说明

namespace

开发者创建空间时指定的空间唯一标示

dir

文件路径(不可以用来渲染dir和name)

name

文件名(不可以用来渲染dir和name)

mimeType

文件类型(MimeType) (中间有'/', 请不要用于渲染name)

mediaType

文件MIME前缀, 多媒体文件类型(取自MimeType)

ext

文件MIME后缀, 文件扩展名(取自MimeType)

year

上传时间的年份

month

上传时间的月份

day

上传时间的日期

hour

上传时间的小时(24小时制)

minute

上传时间的分

second

上传时间的秒

fileSize

上传文件的大小

width

图片宽

height

图片高

exif

图片的Exif信息,里面包含了诸多子项

可以通过exif.xxx来获取

自定义占位符

开发者可以通过下面的代码在上传时传入键值对,

运行时会据此自动对自定义占位符进行渲染。

UploadRequest req = new UploadRequest();

Map<String, String> map = new HashMap<~>();

map.put("var-magic","test1");

Req.setVars(map);

自定义元信息

开发者可以通过下面的代码在上传时传入元信息键值对,

运行时会据此自动对自定义占位符进行渲染,同时系统会对元信息进行结构化保存。

UploadRequest req = new UploadRequest();

Map<String, String> map = new HashMap<~>();

map.put("meta-magic","test2");

Req.setMeta(map);

注意:

当发生重名时, 会以该顺序进行选择: 系统占位符、用户自定义文件meta占位符、用户自定义占位符。在上传的时候, 如果需要指定一个名称为cat的占位符, 需要使用名称为var-cat的参数声明该自定义占位符;meta则对应meta-cat。