开通服务,创建空间用于文件存储,参考 接入指引
Maven 配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <!-- 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
接口描述:
1 2 | // 通过上传策略获取上传Token String getUploadToken(UploadPolicy uploadPolicy) throws MediaException; |
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // 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); uploadPolicy.setMediaEncode(mediaEncodePolicy); // 4. 获取上传Token String token = tokenClient.getUploadToken(uploadPolicy); |
作用:
用于服务端文件上传
类:
MediaClient 和 UploadClient,其中 UploadClient 提供了所有上传选择,可满足个性化上传需求;MediaClient 继承了 UploadClient,同时提供了两个极简的上传接口,可以直接传入本地文件或输入流,更容易上手。
接口描述
// 简单上传接口,直接传入本地文件
Result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 简单上传接口,直接传入输入流 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); |
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | // 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
接口描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | // 检查文件是否存在 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); |
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | // 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.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.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表单上传应包含两段代码:
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // 网页代码 <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); |
注意: