Java-SDK手册¶
安装¶
Java环境¶
JDK 6及以上版本
Maven项目中使用¶
在Maven工程中使用NOS Java SDK只需在pom.xml中加入相应依赖即可
<dependency>
<groupId>com.netease.cloud</groupId>
<artifactId>nos-sdk-java-publiccloud</artifactId>
<version>0.0.2</version>
</dependency>
工程中直接引入jar¶
- 下载包含Java SDK及其依赖的开发包: nos-sdk-java-publiccloud-0.0.2.tar.gz;
- 解压该开发包;
- 将解压后文件夹下lib文件夹中的nos-sdk-java-publiccloud-0.0.2.jar 以及third-party文件夹下的所有jar文件拷贝到您的项目中;
- 在Eclipse中选择您的工程,右击 -> Properties -> Java Build Path -> Add JARs;
- 选中您在第三步拷贝的所有JAR文件;
前言¶
Java SDK提供的接口都在NosClient中实现,并以成员方法的方式对外提供调用。因此使用Java SDK前必须实例化一个NosClient对象。
关于请求参数¶
NosClient中的方法一般都提供两种参数传入方式:
- 普通传参方式:
example:
nosClient.createBucket(bucketName);
- request对象传参方式:
example:
CreateBucketRequest request = new CreateBucketRequest(bucketName); request.setCannedAcl(cannedAcl); nosClient.createBucket(request);
后面的使用指南只以其中的一种传参方式作为例子。
关于异常¶
所有错误异常包装在两个异常类型中,在调用Java SDK接口的时候,捕捉这些异常并打印必要的信息有利于定位问题(ps:在JAVA SDK使用指南的简单示例代码没有重复赘述,使用时注意添加)。
try{
nosClient.XXX("XXX");
//捕捉NOS服务器异常错误
}catch (ServiceException e1){
System.out.println("Error Message: " + e1.getMessage()); //错误描述信息
System.out.println("HTTP Status Code: " + e1.getStatusCode()); //错误http状态码
System.out.println("NOS Error Code: " + e1.getErrorCode()); //NOS服务器定义错误码
System.out.println("Error Type: " + e1.getErrorType()); //NOS服务器定义错误类型
System.out.println("Request ID: " + e1.getRequestId()); //请求ID,非常重要,有利于nos开发人员跟踪异常请求的错误原因
//捕捉客户端错误
}catch(ClientException e2){
System.out.println("Error Message: " + e2.getMessage()); //客户端错误信息
}
初始化¶
- 确定Endpoint
目前有效的Endpoint为:nos-eastchina1.126.net
- 获取密钥对
使用NOS-Java-SDK前,您需要拥有一个有效的 Access Key(包括Access Key和Access Secret)用来进行签名认证。可以通过如下步骤获得:
1)登录 https://c.163.com/ 注册用户
2)注册后,蜂巢会颁发 Access Key 和 Secret Key 给客户,您可以在蜂巢“用户中心”的“Access Key”查看并管理您的Access Key
- 在代码中实例化NosClient
import com.netease.cloud.ClientConfiguration;
import com.netease.cloud.auth.BasicCredentials;
import com.netease.cloud.auth.Credentials;
import com.netease.cloud.services.nos.NosClient;
String accessKey = "your-accesskey";
String secretKey = "your-secretKey ";
Credentials credentials = new BasicCredentials(accessKey, secretKey);
NosClient nosClient = new NosClient(credentials);
nosClient.setEndpoint(endPoint);
注:NosClient是线程安全的,可以并发使用
- 配置NosClient
如果您需要修改NosClient的默认参数,可以在实例化NosClient时传入ClientConfiguration实例。ClientConfiguration是NosClient的配置类,可配置连接超时、最大连接数等参数。通过ClientConfiguration可以设置的参数见下表:
参数 | 描述 | 调用方法 |
---|---|---|
connectionTimeout | 建立连接的超时时间(单位:毫秒)
默认:50000毫秒
|
setConnectionTimeout |
maxConnections | 允许打开的最大HTTP连接数
默认:50
|
setMaxConnections |
socketTimeout | Socket层传输数据超时时间(单位:毫秒)
默认:50000毫秒
|
setSocketTimeout |
maxErrorRetry | 请求失败后最大的重试次数
默认:3次
|
setMaxErrorRetry |
protocol | 使用http协议还是https协议
默认:http协议
|
setProtocol |
带ClientConfiguration参数实例化NosClient的示例代码:
import com.netease.cloud.ClientConfiguration;
import com.netease.cloud.auth.BasicCredentials;
import com.netease.cloud.auth.Credentials;
import com.netease.cloud.services.nos.NosClient;
String accessKey = "your-accesskey";
String secretKey = "your-secretKey ";
Credentials credentials = new BasicCredentials(accessKey, secretKey);
ClientConfiguration conf = new ClientConfiguration();
// 设置NosClient使用的最大连接数
conf.setMaxConnections(200);
// 设置socket超时时间
conf.setSocketTimeout(10000);
// 设置失败请求重试次数
conf.setMaxErrorRetry(2);
// 如果要用https协议,请加上下面语句
conf.setProtocol(Protocol.HTTPS);
NosClient nosClient = new NosClient(credentials,conf);
nosClient.setEndpoint(endPoint);
注意:后面的示例代码默认您已经实例化了所需的NosClient对象
桶管理¶
创建桶¶
您可以通过NosClient.createBucket创建一个桶。示例代码如下:
//设置您要创建桶的名称
CreateBucketRequest request = new CreateBucketRequest(bucketName);
//设置桶的权限,如果不设置,默认为Private
request.setCannedAcl(CannedAccessControlList.PublicRead);
nosClient.createBucket(request);
注意:
1. 桶的命名规范参见API文档
2. NOS中的桶名是全局唯一的,您或者他人已经创建了同名桶,您无法再创建该名称的桶
列举桶¶
您可以通过NosClient.listBuckets列举出当前用户拥有的所有桶。示例代码如下:
for (Bucket bucket : nosClient.listBuckets()) {
System.out.println(" - " + bucket.getName());
}
删除桶¶
您可以通过NosClient.deleteBucket删除指定的桶。示例代码如下:
nosClient.deleteBucket(bucketName);
注意:
如果指定的桶不为空(桶中有文件或者未完成的分块上传),则桶无法删除;
查看桶是否存在¶
您可以通过NosClient.doesBucketExist查看指定的桶是否存在。示例代码如下:
boolean exists = nosClient.doesBucketExist(bucketName);
注意:
您或者他人已经创建了指定名称的桶,doesBucketExist都会返回true。否则返回false
设置桶的ACL¶
桶的ACL包含两类:Private(私有), PublicRead(公共读私有写)。您可以通过NosClient.setBucketAcl设置桶的权限。
权限 | SDK中的对应值 |
---|---|
私有 | CannedAccessControlList.Private |
公共读私有写 | CannedAccessControlList.PublicRead |
示例代码如下:
nosClient.setBucketAcl(bucketName, CannedAccessControlList.Private);
查看桶的ACL¶
您可以通过NosClient.getBucketAcl查看桶的权限。示例代码如下:
CannedAccessControlList acl = nosClient.getBucketAcl(bucketName);
// bucket权限
System.out.println(acl.toString());
文件上传¶
在NOS中,用户的每个文件都是一个Object(对象)。
NOS提供两种文件上传方式:普通上传(PutObject),上传小于或等于100M的文件;分块上传(MultiUpload),大文件可以采用该方式上传。
NOS Java SDK提供了丰富的文件上传接口与功能,主要有:
- 本地文件普通上传
- 支持上传文件时设置文件元数据信息
- 流式上传
- 分块上传
本地文件普通上传¶
对于小对象可以使用putObject接口进行上传,putObject上传支持的最大文件大小为100M,如果上传大于100M的文件需要使用分块上传。本地文件普通上传的示例代码如下:
//要上传文件的路径
String filePath = "your-local-file-path";
try {
nosClient.putObject("your-bucketname","your-objectname", new File(filePath));
}catch (Exception e){
System.out.println(e.getMessage());
}
上传文件时设置文件元数据信息¶
您可以在上传文件时设置文件元数据信息。可以设置的元数据主要有文件的Content-Type和用户自定义元数据信息。 这里以普通上传为例:
String filePath = "your-local-file-path";
ObjectMetadata objectMetadata = new ObjectMetadata();
//设置Content-Type
objectMetadata.setContentType("application/xml");
//设置标准http消息头(元数据)
objectMetadata.setHeader("Cache-Control", "no-cache");
//设置用户自定义元数据信息
Map<String, String> userMeta = new HashMap<String, String>();
userMeta.put("ud", "test");
objectMetadata.setUserMetadata(userMeta);
PutObjectRequest putObjectRequest = new PutObjectRequest("your-bucketname","your-objectname", new File(filePath));
putObjectRequest.setMetadata(objectMetadata);
nosClient.putObject(putObjectRequest);
流式上传¶
try {
ObjectMetadata objectMetadata = new ObjectMetadata();
//设置流的长度,您还可以设置其他文件元数据信息
objectMetadata.setContentLength(streamLength);
nosClient.putObject("your-bucketname","your-objectname", inputStream, objectMetadata)
}catch (Exception e){
System.out.println(e.getMessage());
}
分块上传¶
对于大于100M的对象必须进行分块上传,分块上传的最小单位单位为16K,最后一块可以小于16K,最大单位为100M,较大文件使用分块上传失败的代价比较小,只需要重新上传失败的分块即可; 在文件已经全部存在情况下可以进行分块并发上传。
- 初始化分块上传
//初始化一个分块上传,获取分块上传ID,桶名 + 对像名 + 分块上传ID 唯一确定一个分块上传
is = new FileInputStream("youFilePath");
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest("your-bucketname", "your-objectname");
//您还可以在初始化分块上传时,设置文件的Content-Type
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("application/xml");
initRequest.setObjectMetadata(objectMetadata);
InitiateMultipartUploadResult initResult = nosClient.initiateMultipartUpload(initRequest);
String uploadId = initResult.getUploadId();
- 进行分块上传
下面是顺序上传所有分块的示例,您也可以进行并发上传。
//分块上传的最小单位为16K,最后一块可以小于16K,每个分块都得标识一个唯一的分块partIndex
while ((readLen = is.read(buffer, 0, buffSize)) != -1 ){
InputStream partStream = new ByteArrayInputStream(buffer);
nosClient.uploadPart(new UploadPartRequest().withBucketName("your-bucketname")
.withUploadId(uploadId).withInputStream(partStream)
.withKey("you-objectname").withPartSize(readLen).withPartNumber(partIndex));
partIndex++;
}
- 列出所有分块
//这里可以检查分块是否全部上传,分块MD5是否与本地计算相符,如果不符或者缺少可以重新上传
List<PartETag> partETags = new ArrayList<PartETag>();
int nextMarker = 0;
while (true) {
ListPartsRequest listPartsRequest = new ListPartsRequest("your-bucketname",
"your-objectname", uploadId);
listPartsRequest.setPartNumberMarker(nextMarker);
PartListing partList = nosClient.listParts(listPartsRequest);
for (PartSummary ps : partList.getParts()) {
nextMarker++;
partETags.add(new PartETag(ps.getPartNumber(), ps.getETag()));
}
if (!partList.isTruncated()) {
break;
}
}
- 完成分块上传
CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
"your-bucketname","your-objectname", uploadId, partETags);
CompleteMultipartUploadResult completeResult = nosClient.completeMultipartUpload(completeRequest);
文件下载¶
您可以通过指定桶名和对象名调用getObject接口进行文件下载。NOS Java SDK提供了如下下载方式:
- 流式下载
- 下载到本地文件
- Range下载
- 指定If-Modified-Since进行下载
流式下载¶
NOSObject nosObject = nosClient.getObject("your-bucketname","your-objectname");
//可以通过NOSObject对象的getObjectMetadata方法获取对象的ContentType等元数据信息
String contentType = nosObject.getObjectMetadata().getContentType();
//流式获取文件内容
InputStream in = nosObject.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {
String line;
try {
line = reader.readLine();
if (line == null) break;
System.out.println("\n" + line);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
注意:
- NosClient.getObject获取的流一定要显式的close,否则会造成资源泄露。
下载到本地文件¶
你可以通过调用NOS Java SDK的getObject接口直接将NOS中的对象下载到本地文件
String destinationFile = "your-local-filepath";
GetObjectRequest getObjectRequest = new GetObjectRequest("your-bucketname","your-objectname");
ObjectMetadata objectMetadata = nosClient.getObject(getObjectRequest, new File(destinationFile));
Range下载¶
NOS Java SDK支持范围(Range)下载,即下载指定对象的指定范围的数据。
GetObjectRequest getObjectRequest = new GetObjectRequest("your-bucketname","your-objectname");
getObjectRequest.setRange(0, 100);
NOSObject nosObject = nosClient.getObject(getObjectRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {
String line;
try {
line = reader.readLine();
if (line == null) break;
System.out.println("\n" + line);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
指定If-Modified-Since进行下载¶
下载文件时,您可以指定If-Modified-Since参数,满足文件的最后修改时间小于等于If-Modified-Since参数指定的时间,则不进行下载,否则正常下载文件。
//假设需要下载的文件的最后修改时间为: Date lastModified;
//lastModified小于等于指定If-Modified-Since参数
GetObjectRequest getObjectRequest = new GetObjectRequest("your-bucketname","your-objectname");
Date afterTime = new Date(lastModified.getTime() + 1000);
getObjectRequest.setModifiedSinceConstraint(afterTime);
//此时nosObject等于null
NOSObject nosObject = client.getObject(getObjectRequest);
Date beforeTime = new Date(lastModified.getTime() -1000);
getObjectRequest.setModifiedSinceConstraint(beforeTime);
//此时nosObject不等于null,可以正常获取文件内容
nosObject = client.getObject(getObjectRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {
String line;
try {
line = reader.readLine();
if (line == null) break;
System.out.println("\n" + line);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
文件管理¶
您可以通过NOS Java SDK进行如下文件管理操作:
- 判断文件是否存在
- 文件删除
- 获取文件元数据信息
- 文件复制(copy)
- 文件重命名(move)
- 列举桶内文件
- 生成私有对象可下载的URL连接
判断文件是否存在¶
您可以通过NosClient.doesObjectExist判断文件是否存在。
boolean isExist = nosClient.doesObjectExist("your-bucketname","your-objectname");
文件删除¶
您可以通过NOSClient.deleteObject删除单个文件
nosClient.deleteObject("your-bucketname","your-objectname");
您还可以通过NOSClient.deleteObjects一次删除多个文件
try {
DeleteObjectsResult result = nosClient.deleteObjects(deleteObjectsRequest);
List<DeletedObject> deleteObjects = result.getDeletedObjects();
//print the delete results
for (DeletedObject items: deleteObjects){
System.out.println(items.getKey());
}
// 部分对象删除失败
} catch (MultiObjectDeleteException e) {
List<DeleteError> deleteErrors = e.getErrors();
for (DeleteError error : deleteErrors) {
System.out.println(error.getKey());
}
} catch (ServiceException e) {
//捕捉nos服务器异常错误
} catch (ClientException ace) {
//捕捉客户端错误
}
获取文件元数据信息¶
您可以通过NOSClient.getObjectMetadata获取文件元数据信息
nosClient.getObjectMetadata("your-bucketname","your-objectname");
文件复制(copy)¶
您可以通过NOSClient.copyObject接口实现文件拷贝功能。 NOS支持桶内copy以及相同用户的跨桶copy。
nosClient.copyObject("source-bucket", "source-object", "dst-bucket", "dst-object");
文件重命名(move)¶
您可以通过NOSClient.moveObject接口实现文件重命名功能。 NOS仅支持桶内move。
nosClient.moveObject("bucket-name", "source-object-key", "bucket-name", "dst-object-key");
列举桶内文件¶
您可以通过NOSClient.listObjects列出桶里的文件。listObjects接口如果调用成功,会返回一个ObjectListing对象,列举的结果保持在该对象中。
ObjectListing的具体信息如下表所示:
方法 | 含义 |
---|---|
List<NOSObjectSummary> getObjectSummaries() | 返回的文件列表(包含文件的名称、Etag的元数据信息) |
String getPrefix() | 本次查询的文件名前缀 |
String getDelimiter() | 文件分界符 |
String getMarker() | 这次List Objects的起点 |
int getMaxKeys() | 响应请求内返回结果的最大数目 |
String getNextMarker() | 下一次List Object的起点 |
boolean isTruncated() | 是否截断,如果因为设置了limit导致不是所有的数据集都返回,则该值设置为true |
List<String> getCommonPrefixes() | 如果请求中指定了delimiter参数,则返回的包含CommonPrefixes元素。该元素标明以delimiter结尾,并有共同前缀的对象的集合 |
NOSClient.listObjects接口提供两种调用方式:简单列举、通过ListObjectsRequest列举
简单列举¶
简单列举只需指定需要列举的桶名,最多返回100条对象记录,建议桶内对象数较少时(小于100)使用。
ObjectListing objectListing = nosClient.listObjects("your-bucketname");
List<NOSObjectSummary> sums = objectListing.getObjectSummaries();
for (NOSObjectSummary s : sums) {
System.out.println("\t" + s.getKey());
}
通过ListObjectsRequest列举¶
您还可以通过设置ListObjectsReques参数实现各种灵活的查询功能。ListObjectsReques的可设置的参数如下:
设置方法 | 作用 |
---|---|
setPrefix(String prefix) | 限定返回的object key必须以prefix作为前缀 |
setDelimiter(String delimiter) | 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素——CommonPrefixes |
setMarker(String marker) | 字典序的起始标记,只列出该标记之后的部分 |
setMaxKeys(Integer maxKeys) | 限定返回的数量,返回的结果小于或等于该值(默认值为100) |
1、分页列举桶内的所有文件:¶
List<NOSObjectSummary> listResult = new ArrayList<NOSObjectSummary>();
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName("your-bucketname");
listObjectsRequest.setMaxKeys(50);
ObjectListing listObjects = nosClient.listObjects(listObjectsRequest);
do {
listResult.addAll(listObjects.getObjectSummaries());
if (listObjects.isTruncated()) {
ListObjectsRequest request = new ListObjectsRequest();
request.setBucketName(listObjectsRequest.getBucketName());
request.setMarker(listObjects.getNextMarker());
listObjects = nosClient.listObjects(request);
} else {
break;
}
} while (listObjects != null);
2、使用Delimiter模拟文件夹功能¶
假设桶内有如下对象:a/1.jpg、a/2.jpg、a/b/1.txt、a/b/2.txt,列举a文件夹下的文件及子文件夹的示例代码如下:
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName("your-bucketname");
listObjectsRequest.setDelimiter("/");
listObjectsRequest.setPrefix("a/");
ObjectListing listing = nosClient.listObjects(listObjectsRequest);
// 遍历所有Object
System.out.println("Objects:");
for (NOSObjectSummary objectSummary : listing.getObjectSummaries()) {
System.out.println(objectSummary.getKey());
}
// 遍历所有CommonPrefix
System.out.println("CommonPrefixs:");
for (String commonPrefix : listing.getCommonPrefixes()) {
System.out.println(commonPrefix);
}
示例代码的输出如下:
Objects:
a/1.jpg
a/2.jpg
CommonPrefixs:
a/b/
生成私有对象可下载的URL连接¶
NOS Java SDK支持生成可下载私有对象的URL连接,您可以将该链接提供给第三方进行文件下载:
Credentials credentials;
credentials = new BasicCredentials(accessKey, secretKey);
NosClient client = new NosClient(credentials);
// 配置client
String bucketName = "your-bucketname";
String key = "object-name";
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
generatePresignedUrlRequest.setExpiration(new Date(System.currentTimeMillis()+3600*1000*24));
// 设置可下载URL的过期时间为1天后
URL url = nosClient.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println(url);
文件上传下载工具类:TransferManager¶
前文提到的是NOS Java SDK提供的基础接口,为方便用户进行文件上传下载,NOS Java SDK提供了封装更好、使用更方便的工具类:TransferManager。
TransferManager的初始化¶
//先实例化一个NosClient
String accessKey = "your-accesskey";
String secretKey = "your-secretKey ";
Credentials credentials = new BasicCredentials(accessKey, secretKey);
NosClient nosClient = new NosClient(credentials);
nosClient.setEndpoint(endPoint);
//然后通过nosClient对象来初始化TransferManager
TransferManager transferManager = new TransferManager(nosClient);
使用TransferManager进行文件上传¶
TransferManager会根据文件大小,选择是否进行分块上传。当文件小于等于16M时,TransferManager会自动调用PutObject接口,否则TransferManager会自动对文件进行分块上传。
1、上传本地文件:
如果指定上传的本地文件大于16M,TransferManager会自动对文件进行分块,并发调用分块上传接口进行上传,大大提高上传文件的速度。
//上传文件
Upload upload = transferManager.upload("your-bucketname", "your-objectname", new File("your-file"));
UploadResult result = upload.waitForUploadResult();
2、流式上传:
您也可以使用TransferManager进行流式上传,但是相比本地文件上传,流式上传无法做到多个分块并发上传,只能一个分块一个分块顺序上传。
注意: 如果您调用TransferManager流式上传的文件大于100M,必须指定对象的ContentLength
//流式上传文件
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.length());
Upload upload = transferManager.upload("your-bucketname", "your-objectname", inputStream, objectMetadata);
UploadResult result = upload.waitForUploadResult();
3、上传目录
您可以使用TransferManager将某个目录下的文件全部上传到NOS,对象名即文件名,不支持多级目录
MultipleFileUpload result = transferManager.uploadDirectory("your-buckename", null, new File("dirPath"), false);
result.waitForCompletion();
4、下载文件
File file = new File("your-destFile");
Download download = transferManager.download("your-bucketname", "your-objectname", file);
download.waitForCompletion();