开通服务,创建空间用于文件存储,参考 接入指引
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.2.7</version> </dependency>
点击下面链接下载 Java SDK (含 Demo)
分别在 MediaClientDemo、ManagerClientDemo、UploadClientDemo 三个类的初始化配置中,填入开发者自己的AK、SK 和 namespace后,直接运行main函数即可。示例如下:
如何获取 AK 和 SK?
进入控制台 操作路径为:账户管理 -> 百川秘钥,如图示:
作用:
根据上传策略生成上传Token,一般用于鉴权服务器
类:
UploadTokenClient
接口描述:
// 通过上传策略获取上传Token String getUploadToken(UploadPolicy uploadPolicy) throws MediaException;
示例代码
// 1. 定义全局配置信息 MediaConfiguration configuration = new MediaConfiguration(); 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); // 3.1 上传策略中设置转码 MediaEncodePolicy mediaEncodePolicy = new MediaEncodePolicy(); MediaEncodePolicyRequest encodeCommand = new MediaEncodePolicyRequest(); List<MediaEncodePolicyRequest> tasks = new ArrayList<MediaEncodePolicyRequest>(); encodeCommand.setOutput(new GlobalFileResource(configuration.getNamespace(), "/media_encode_output", "out.mp4")); encodeCommand.setUsePreset( "false"); encodeCommand.setForce("true"); encodeCommand.setEncodeTemplate("mytemplate"); tasks.add(encodeCommand); mediaEncodePolicy.setTasks(tasks); mediaEncodePolicy.setNotifyUrl("http://rs.media.aliyun.com/notify"); uploadPolicy.setMediaEncode(mediaEncodePolicy); // 4. 获取上传Token String token = tokenClient.getUploadToken(uploadPolicy);
作用:
用于服务端文件上传
类:
MediaClient 和 UploadClient,其中 UploadClient 提供了所有上传选择,可满足个性化上传需求;MediaClient 继承了 UploadClient,同时提供了两个极简的上传接口,可以直接传入本地文件或输入流,更容易上手。
接口描述
// 简单上传接口,直接传入本地文件
Result
// 简单上传接口,直接传入输入流 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.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); // 通过resource批量扫描黄图,最多一次提交50张 Result<MultiScanResult> scanPorn(FileResource... resources); // 视频转码服务 Result<String> mediaEncode(MediaEncodeRequest mediaEncodeRequest); // 视频转码结果获取 Result<MediaEncodeTask> getMediaEncodeResult(String mediaEncodeTaskId); // 视频截图任务 Result<String> snapshot(SnapshotRequest request); // 视频截图任务结果获取 Result<Void> getSnapshotResult(String taskId); // 通过resource批量广告图,最多一次提交50张(beta) Result<MultiScanResult> scanAdvertising(FileResource... resources); // 生成私有空间鉴权URL Result<String> generateSignedUrl(String domain, String uri, String signedKey, Long expired);
示例代码
// 0.1 定义全局配置信息 MediaConfiguration configuration = new MediaConfiguration(); 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()); } // 8. 通过resource批量扫描黄图 FileResource file1 = new FileResource(); file1.setDir("/"); file1.setName("Desert.jpg"); FileResource f2 = new FileResource(); file2.setDir("/"); file2.setName("5中文"); Result<MultiScanResult> result = client.scanPorn(file1, file2); // 9. 视频转码 MediaEncodeRequest request = new MediaEncodeRequest(); request.setInput(new GlobalFileResource("service", "/test", "input.mp4")); request.setOutput(new GlobalFileResource("service", "/test", "ouput.mp4")); request.setWatermark(new GlobalFileResource("service", "/test", "watermark.png")); request.setNotifyUrl("http://sample-host/notify"); request.setEncodeTemplate("test-encode-template"); request.setWatermarkTemplate("test-watermark-template"); request.setUsePreset(false); request.setForce(true); request.setSeek("0"); request.setDuration("10"); Result r = client.mediaEncode(request); // 10. 视频转码结果获取 Result r = client.getMediaEncodeResult("my-task-id"); // 11. 视频截图 SnapshotRequest request = new SnapshotRequest(); request.setInput(new GlobalFileResource("service", "/test", "input.mp4")); request.setOutput(new GlobalFileResource("service", "/test", "ouput.jpg")); request.setNotifyUrl("http://sample-host/notify"); request.setTime("5"); Result r = client.snapshot(request); // 12. 视频截图结果获取 Result r = client.getSnapshotResult("my-task-id"); // 13. 批量扫描广告(beta) Result<MultiScanResult> r = null; FileResource file1 = new FileResource(); file1.setDir("/"); file1.setName("Desert.jpg"); FileResource file2 = new FileResource(); file2.setDir("/"); file2.setName("测试.jpg"); r = client.scanAdvertising(file1, file2); // 14. 生成私有空间鉴权URL Result<String> r = null; r = client.generateSignedUrl("访问域名", "访问URI", "鉴权Key", 3000l);
使用说明
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.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); |
注意: