Amazon S3云存储服务器的功能及编程接口

来源:互联网 发布:阿里云域名绑定服务器 编辑:程序博客网 时间:2024/04/30 02:31

Amazon S3是一种云上的存储服务器,其功能仅在于存储。和普通的服务器不同,它没有操作界面,连一般的SSH命令登录功能都没有。和它打交道的话,一种办法是用它的管理界面,另一种是借助其编程接口。


1.名词和术语

AWS Account:Amazon Web Service Account, 一般一个公司会申请一个帐户,可以认为管理员帐户。

IAM User:一般AWS只有少数人掌握,为了操作的方式,添加子帐户称为IAM帐户,每个帐户有不同的权限。无论是AWS还是IAM帐户,都有一个Access Key ID和一个Secret Key。在Amazon Web 管理界面上登录时使用帐户名,而用编程接口交互时都用的是Access Key ID和Secret Key,其中ID是16个字符,Secret是40个字节。

Bucket:    可以理解为一个很大的磁储硬盘,其容量以T为单位,当然,你肯花的钱越多就可以买到更大容易的S3。一个AWS帐户可以创建N个(N<100)个bucket。bucket的名称作为domain name的一部分,例如,如果bucket名称叫mybucket,则其全称为http://mybucket.s3.amazonaws.com/

Object:Bucket的文件,不过在这里称为资源更好些。在Bucket所有的Object呈Flat状排列,每个Object有一个唯一的Key,可以理解为URI。需要注意的是,Bucket里没有目录树的概念,虽然一个Object Key可能显示为 a/b/c/my.jpg,并不意味着有a, b, c三个目录和一个my.jpg的文件。事实上,只有一个资源,其名称Key就是一个全路径而已。

     Object Key: 表示其名称,在bucket内全局唯一,实际就是一个可带斜线/的字符串,如/a/b/c/my.jpg

     Object Meta: 描述其大小,ACL等

     Object Value: 就是Object的内容,其长度为Meta里长度

     Object Version: 默认不带版本支持的,只要显示的设置bucket之后才有Version概念

Access Control:S3上的Object默认是不能public访问的,这意味着,你上传一个Object的Key=a/my.html,并不能直接通过http://mybucket.s3.amazonaws.com/a/my.html直接访问,会提示Access Denied,只要在设置权限(ACL或Policy之后才可以访问)


2.常用操作

S3服务器提供了SOAP/HTTP接口,官方称为REST API。同时为了使用了方便在其上封装了一层SDK,支持Java, PHP, .Net, Ruby接口,可惜的暂时没有C++接口。一般程序员们可以用它的SDK,还是很方便的,满足大部分操作的需求。

先声明一些变量

[java] view plaincopy
  1.     String accessKeyID = "xxxxxxxxxxxxxx";  
  2.     String secretKey = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyy";  
  3.     String bucketName = "zzzzzzzzzz";  
  4.       
  5.     AWSCredentials credentials;  
  6.         AmazonS3 s3Client;  
  7.         credentials = new BasicAWSCredentials(accessKeyID, secretKey);  
  8.         s3Client = new AmazonS3Client(credentials);  
(1) 查看可用的bucket

只要给定了AWS Account / IAM User的ID和Secret,就可以直接遍例出所有该用户可以访问的bucket。当然,bucket一般是建议由管理员在页面上设置的,一般在程序里不需要对bucket进行操作。

[java] view plaincopy
  1. List<Bucket> buckets = s3Client.listBuckets();  
  2.   
  3. for (Bucket bucket : buckets)   
  4. {             
  5.     System.out.println("Bucket: " + bucket.getName());        
  6. }         

(2) 查看bucket下所有的object
[java] view plaincopy
  1. ObjectListing objects = s3Client.listObjects(myBucketName);  
  2. do   
  3. {  
  4.     for (S3ObjectSummary objectSummary : objects.getObjectSummaries())   
  5.     {  
  6.         System.out.println("Object: " + objectSummary.getKey());                  
  7.     }                                 
  8.     objects = s3Client.listNextBatchOfObjects(objects);  
  9. while (objects.isTruncated());  
实际上,可以按前缀进行list操作,不然要list的东西太多了。
[java] view plaincopy
  1. ListObjectsRequest listObjectsRequest = new ListObjectsRequest()  
  2.     .withBucketName(bucketName)  
  3.     .withPrefix(prefix)  
  4.     ;     
  5.   
  6. ObjectListing objects = s3Client.listObjects(listObjectsRequest);  
  7.               ...  

【补充 1012-08-21】

按目录层次查询:虽然S3服务器上并无目录的概念,但是在List接口上添加了按层次查询的支持,具体就是Prefix和Delimiter的结合,一般Delimiter就是斜线/。具体解释一下,就是如果存在:

china/beijing/a.txt

china/beijing/b.txt

china/anhui/c.txt

china/all.txt

想列出china/下的第一级层次,可以设置prefix="china/", delimiter="/",通过ObjectListing的getCommonprefixes()得到china/beijing/, china/anhui/共两项(子目录),通过getObjectSummaries()得到china/all.txt (叶子节点)。

[java] view plaincopy
  1. ListObjectsRequest listObjectsRequest = new ListObjectsRequest()  
  2.     .withBucketName(bucketName)  
  3.     .withPrefix(prefix)  
  4.     .withDelimiter("/")  
  5.     ;  
  6.   
  7.   
  8.    ObjectListing objects = s3Client.listObjects(listObjectsRequest);  
  9.    do   
  10.    {  
  11.     for(String objKey : objects.getCommonPrefixes())  
  12.     {  
  13.         System.out.println("+ " + objKey);  
  14.     }     
  15.       
  16.        for (S3ObjectSummary objectSummary : objects.getObjectSummaries())   
  17.        {  
  18.         String objKey = objectSummary.getKey();  
  19.         //keyList.add(objKey);  
  20.         System.out.println(objKey);  
  21.        }        
  22.        objects = s3Client.listNextBatchOfObjects(objects);  
  23.    } while (objects.isTruncated());      


(3) 上传文件

需要强调的是,本地文件系统有目录的概念,但是在S3上没有目录的概念,其URI只是作为Object的key出现。这里顺便在添加的时候赋予该Object一个Public Read权限,以便可以匿名访问。

[java] view plaincopy
  1. File file = new File(localPath);          
  2.   
  3. // 默认添加public权限  
  4. s3Client.putObject(new PutObjectRequest(bucketName, s3Path, file)  
  5.     .withCannedAcl(CannedAccessControlList.PublicRead));   


  (4) 多线程上传

在文件比较大的时候,有必要用多线程上传。

[java] view plaincopy
  1. TransferManager tm = new TransferManager(s3Client);  
  2. TransferManagerConfiguration conf = tm.getConfiguration();  
  3.   
  4. int threshold = 4 * 1024 * 1024;  
  5. conf.setMultipartUploadThreshold(threshold);  
  6. tm.setConfiguration(conf);  
  7.   
  8. Upload upload = tm.upload(bucketName, s3Path, new File(localPath));  
  9. TransferProgress p = upload.getProgress();  
  10.   
  11. while (upload.isDone() == false)  
  12. {             
  13.     int percent =  (int)(p.getPercentTransfered());  
  14.     System.out.print("\r" + localPath + " - " + "[ " + percent + "% ] "   
  15.             + p.getBytesTransfered() + " / " + p.getTotalBytesToTransfer() );  
  16.     // Do work while we wait for our upload to complete...  
  17.     Thread.sleep(500);  
  18. }  
  19. System.out.print("\r" + localPath + " - " + "[ 100% ] "   
  20.         + p.getBytesTransfered() + " / " + p.getTotalBytesToTransfer() );  
  21.   
  22. // 默认添加public权限  
  23. s3Client.setObjectAcl(bucketName, s3Path, CannedAccessControlList.PublicRead);  

(5) 删除Object
[java] view plaincopy
  1. DeleteObjectRequest request = new DeleteObjectRequest(bucketName, s3Path);  
  2. s3Client.deleteObject(request);  


(6) 重命名Object

         没有直接的命名接口,而是借用copy接口来实现。

         重命名分为2步:(1) 调用copy接口,作一个拷贝
                                       (2) 调用delete接口,删除原来的Object

[java] view plaincopy
  1. System.out.println(s3PathOld + " -> " + s3PathNew);  
  2. S3Object obj = s3Client.getObject(new GetObjectRequest(bucketName, s3PathOld));  
  3.        s3Client.copyObject(bucketName, s3PathOld,  
  4.             bucketName, s3PathNew);  
  5.        deleteFile(s3PathOld); 
原创粉丝点击