转自:http://ywskycn.com/cloud-computing/jets3t-use.html
最近需要使用JetS3t做一些开发工作,所以收集了一些相关的资料整理成中文。本文的pdf版本可从这里下载:download。
1. JetS3t简介
JetS3t[1]是一个用于与Amazon Simple Storage Service[2](Amazon S3)和Amazon CloudFront[3]交互的Java开源工具箱。它将Amazon S3的一些API抽象成常见的Java方法和类,方便开发人员更好的与S3进行交互。JetS3t开发套件中包括5个主要的应用程序:
- Cockpit:一个GUI工具用户传输文件,查看和管理Amazon S3帐号中的内容。
- Synchronize:用于同步用户计算机上的目录和Amazon S3账户的命令行工具,最适合于不同的计算机之间同步文件与备份。
- Gatekeeper:一个Servlet可以作为访问Amazon S3账户的中介,其它没有S3账户的客户端可以利用这个Servlet实现上传,下载,删除等操作。
- CockpitLite:Cockpit的简约版本,它通过中介Gatekeeper服务实现所有操作。
- Uploader:一个GUI应用程序,提供一个通过Gatekeeper服务实现文件上传的简单向导。
这5个应用程序都是基于JetS3t工具箱开发,展示了如何利用该工具箱做进一步的开发。JetS3t采用Apache License,Version 2.0开源协议。
2. 代码示例
本节主要介绍有关于JetS3t的简单实例代码。JetS3t依赖以下类库:
Library | URL |
HttpClient 3.1 | http://jakarta.apache.org/commons/httpclient/ |
Log4J | http://logging.apache.org/log4j/docs/ |
Bare Bones Browser Launcher | http://www.centerkey.com/java/browser/ |
Nuvola Icon Library | http://icon-king.com/ |
Java Uuid Generator (JUG) | http://jug.safehaus.org/Home |
Apache Axis 1.4 | http://ws.apache.org/axis/ |
Bouncy Castle Crypto APIs | http://www.bouncycastle.org/ |
Java XMLBuilder | http://code.google.com/p/java-xmlbuilder/ |
2.1 基本操作
2.1.1 Connecting to S3
使用JetS3t对S3进行任何操作都需要提供S3账户的awsAccessKey和awsSecretKey。有关于这两个Keys的获取如下图所示:
由于S3只有两种存储结构,Bucket和Object。相对应JetS3t中的对象为:
- S3Bucket:S3中的Object都存在某个Bucket之中,每个Bucket在S3中都有唯一的名字。
- S3Object:S3的Bucket中的存储数据类型,每个Object都有一个key值。
连接到S3的实例代码如下:
String awsAccessKey = “YOUR_AWS_ACCESS_KEY”; String awsSecreyKey = “YOUR_AWS_SECREY_KEY”; AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey); |
为了与S3交互,需要创建一个S3Service的对象。这里采用的REST/HTTP协议,这也是JetS3t提供的最可靠的协议。
S3Service s3Service = new RestS3Service(awsCredentials); // list all the buckets S3Bucket myBuckets[] = s3Service.listAllBuckets(); System.our.println(“How many buckets do I have in S3?” + myBuckets.length); |
2.1.2 Create a Bucket
为了将Object存储到S3中,首先需要创建一个bucket,即创建object的容器。
S3Bucket testBucket = s3Service.createBucket(“test-bucket”); System.out.println(“Created test bucket: ” + testBucket.getName()); |
因为bucket的名字是S3全局唯一的,因此这里的“test-bucket”需要换成一个与其它buckets不重复的名字。在创建bucket时可以设置location参数,用来表示希望将该bucket存储在哪个地区的数据中心,例如下面的例子就是将bucket存储在Amazon设在欧洲的数据中心。
S3Bucket euBucket = s3Service.createBucket(“eu-bucket”, S3Bucket.LOCATION_EUROPE); |
这里可选的location有:US, US_STANDARD, US_WEST, 和EUROPE。
2.1.3 Uploading Data/Files
JetS3t将S3中的object封装成S3Object,因此在将数据上传到S3之前,我们需要创建一个S3Object(并用key/name标识),并通过S3Service上传到相应的bucket中。下面的代码创建了一个S3Object对象,并将上传前和上传后的对象信息打印出来。上传之后的对象会增加一些额外的信息,例如文件的最后修改时间等。
// Create an empty object with a key/name, and print the object’s details. S3Object object = new S3Object(“object”); System.out.println(“S3Object before upload: ” + object); // Upload the object to our test bucket in S3. object = s3Service.putObject(testBucket, object); // Print the details about the uploaded object, which contains more information. System.out.println(“S3Object after upload: ” + object); |
上面的代码创建了一个名为“object”的空对象。当然,如果知道数据的Content/Mime类型(例如text/plain),也可以设置object相应的数据内容。S3Object不支持从输入流直接获取数据信息,但是JetS3t提供了两类方法用来获取文件或字符串数据信息。相应的构造方法会自动的设置object的Content-Type和Content-Length的信息。
// Create an S3Object based on a string, with Content-Length set automatically and // Content-Type set to “text/plain” String stringData = “Hello World!”; S3Object stringObject = new S3Object(“HelloWorld.txt”, stringData); // Create an S3Object based on a file, with Content-Length set automatically and // Content-Type set based on the file’s extension (using the Mimetypes utility class) File fileData = new File(“src/org/jets3t/samples/CodeSamples.java”); S3Object fileObject = new S3Object(fileData); |
如果上传的数据既不是文件也不是字符串,那么可以通过输入流来实现数据上传,但是需要手工设置Content-Length信息。
// Create an object containing a greeting string as input stream data. String greeting = “Hello World!”; S3Object helloWorldObject = new S3Object(“HelloWorld2.txt”); ByteArrayInputStream greetingIS = new ByteArrayInputStream(greeting.getBytes()); helloWorldObject.setDataInputStream(greetingIS); helloWorldObject.setContentLength(greetingIS.available()); helloWorldObject.setContentType(“text/plain”); // Upload the data objects. s3Service.putObject(testBucket, stringObject); s3Service.putObject(testBucket, fileObject); s3Service.putObject(testBucket, helloWorldObject); // Print details about the uploaded object. System.out.println(“S3Object with data: ” + helloWorldObject); |
为了确保在传输过程中不出现异常问题,我们需要检查S3接收到的数据的哈希值与本地原始文件的哈希值是否匹配。实现该机制的一个简单的方法就是在上传数据之前,设置object的Content-MD5值。当你使用File-或String-based的S3Object构造方法时,JetS3t将会自动设置Content-MD5的值。
S3Object objectWithHash = new S3Object(testBucket, “HelloWorld.txt”, stringData); System.out.println(“Hash value: ” + objectWithHash.getMd5HashAsHex()); |
当你使用的不是这类构造方法时,那么需要手工设置Content-MD5值。JetS3t提供相应的方法来计算一个输入流或者字节流的相应的哈希值。
ByteArrayInputStream dataIS = new ByteArrayInputStream( “Here is my data”.getBytes(Constants.DEFAULT_ENCODING)); byte[] md5Hash = ServiceUtils.computeMD5Hash(dataIS); dataIS.reset(); stringObject = new S3Object(“MyData”); stringObject.setDataInputStream(dataIS); stringObject.setMd5Hash(md5Hash); |
2.1.4 Downloading Objects
如果只是希望了解S3账户中某个文件的一些信息(即HEAD信息),那么不需要下载整个object。这里的HEAD信息包括object的大小,时间,Content Type等等。
// Retrieve the HEAD of the data object we created previously. S3Object objectDetailsOnly = s3Service.getObjectDetails(testBucket, “helloWorld.txt”); System.out.println(“S3Object, details only: ” + objectDetailsOnly); |
如果希望获取object的内容信息,可以通过下列代码实现:
// Retrieve the whole data object we created previously S3Object objectComplete = s3Service.getObject(testBucket, “helloWorld.txt”); System.out.println(“S3Object, complete: ” + objectComplete); // Read the data from the object’s DataInputStream using a loop, and print it out. System.out.println(“Greeting:”); BufferedReader reader = new BufferedReader( new InputStreamReader(objectComplete.getDataInputStream())); String data = null; while ((data = reader.readLine()) != null) { System.out.println(data); } |
同上传数据相同,如果需要判断下载过程中是否出现异常,通过检查object的哈希值即可。
S3Object downloadedObject = s3Service.getObject(testBucket, “helloWorld.txt”); String textData = ServiceUtils.readInputStreamToString( downloadedObject.getDataInputStream(), “UTF-8″); boolean valid = downloadedObject.verifyData(textData.getBytes(“UTF-8″)); System.out.println(“Object verified? ” + valid); |
2.1.5 Listing Your Buckets/Objects
通过上面的代码,我们S3的账户中现在已经有了一个bucket,并且包含了一些objects。我们可以罗列出所有bucket和object的信息。需要说明的是,罗列出的object信息要少于方法getObject和getObjectDetails返回的object信息。
// List all your buckets. S3Bucket[] buckets = s3Service.listAllBuckets(); // List the object contents of each bucket. for (int b = 0; b < buckets.length; b++) { System.out.println(“Bucket ‘” + buckets[b].getName() + “‘ contains:”); // List the objects in this bucket. S3Object[] objects = s3Service.listObjects(buckets[b]); // Print out each object’s key and size. for (int o = 0; o < objects.length; o++) { System.out.println(” ” + objects[o].getKey() + ” (” + objects[o].getContentLength() + ” bytes)”); } } |
当用户希望获取一个bucket中某一类对象的信息时,这种方法非常适用,因为它不需要下载所有object的内容。
// List only objects whose keys match a prefix. String prefix = “Reports”; String delimiter = null; // Refer to the S3 guide for more information on delimiters S3Object[] filteredObjects = s3Service.listObjects(testBucket, prefix, delimiter); |
2.1.6 Deleting Buckets/Objects
Object可以很容易被删除,而Bucket只有其为空时才可被删除。
// If you try to delete your bucket before it is empty, it will fail. try { // This will fail if the bucket isn’t empty. s3Service.deleteBucket(testBucket.getName()); } catch (S3ServiceException e) { e.printStackTrace(); } // Delete all the objects in the bucket s3Service.deleteObject(testBucket, object.getKey()); s3Service.deleteObject(testBucket, helloWorldObject.getKey()); // Now that the bucket is empty, you can delete it. s3Service.deleteBucket(testBucket.getName()); System.out.println(“Deleted bucket ” + testBucket.getName()); |
2.1.7 Copying Objects
可以在Bucket内部以及不同的bucket之间实现object的拷贝。
// Create a target S3Object S3Object targetObject = new S3Object(“targetObjectWithSourcesMetadata”); boolean replaceMetadata = false; s3Service.copyObject(“test-bucket”, “HelloWorld.txt”, “destination-bucket”, targetObject, replaceMetadata); |
也可以在拷贝对象的同时更新相应的metadata信息。
targetObject = new S3Object(“HelloWorld.txt”); targetObject.addMetadata(S3Object.METADATA_HEADER_CONTENT_TYPE, “text/html”); replaceMetadata = true; s3Service.copyObject(“test-bucket”, “HelloWorld.txt”, “test-bucket”, targetObject, replaceMetadata); |
2.1.8 Moving and Renaming Objects
可以在同一地区的数据中心中将object从一个bucket移动到另外一个bucket中。一个文件移动操作由拷贝和删除操作组成。若拷贝操作失败,那么这个object不会被删除。但是如果最终的删除操作失效,那么这个object将会在源bucket和目的bucket中都出现。
s3Service.moveObject(“test-bucket”, “HelloWorld.txt”, “destination-bucket”, targetObject, false); // You can move an object to a new name in the same bucket. This is essentially a rename operation. s3Service.moveObject(“test-bucket”, “HelloWorld.txt”, “test-bucket”, new S3Object(“NewName.txt”), false); // To make renaming easier, JetS3t has a shortcut method especially for this purpose. s3Service.renameObject(“test-bucket”, “HelloWorld.txt”, targetObject); |
2.1.9 Bucket Versioning
S3的bucket提供versioning特性,允许object在被更新或删除的时候保存之前的版本。这个特性也使得用户不用去担心一些重要的数据因为意外的覆盖或删除操作而丢失。在默认设置中,S3并没有开启versioning功能,需要用户手工开启该功能。而一旦开启该功能,用户可以通过唯一的版本标识来访问管理某一版本的object数据。
// Create a bucket to test versioning S3Bucket versioningBucket = s3Service.getOrCreateBucket(“test-versioning”); String vBucketName = versioningBucket.getName(); // Check bucket versioning status for the bucket S3BucketVersioningStatus versioningStatus = s3Service.getBucketVersioningStatus(vBucketName); System.out.println(“Versioning enabled ? ” + versioningStatus.isVersioningEnabled()); // Suspend (disable) versioning for a bucket — will have no effect if bucket versioning is not yet // enabled. This will not delete any existing object versions. s3Service.suspendBucketVersioning(vBucketName); // Enable versioning for a bucket. s3Service.enableBucketVersioning(vBucketName); // Once versioning is enabled you can GET, PUT, copy and delete objects as normal. Every change to // an object will cause a new version to be created. // Store and update and delete an object in the versioning bucket S3Object versionedObject = new S3Object(“versioned-object”, “Initial version”); s3Service.putObject(vBucketName, versionedObject); versionedObject = new S3Object(“versioned-object”, “Second version”); s3Service.putObject(vBucketName, versionedObject); versionedObject = new S3Object(“versioned-object”, “Final version”); s3Service.putObject(vBucketName, versionedObject); |
如果通过普通的方法来获取一个开启了versioning功能的object,那么S3将反馈该object的最新版本的数据信息,并且用户可以查看该数据的版本ID。
versionedObject = s3Service.getObject(vBucketName, “versioned-object”); String finalVersionId = versionedObject.getVersionId(); System.out.println(“Version ID: ” + finalVersionId); |
如果将一个versioned的object删除,那么上面介绍的一些普通的方法将不再可用。
s3Service.deleteObject(vBucketName, “versioned-object”); try { s3Service.getObject(vBucketName, “versioned-object”); } catch (S3ServiceException e) { if (e.getResponseCode() == 404) { System.out.println(“Is deleted object versioned? ” + e.getResponseHeaders().get(Constants.AMZ_DELETE_MARKER)); System.out.println(“Delete marker version ID: ” + e.getResponseHeaders().get(Constants.AMZ_VERSION_ID)); } } |
这时候就需要使用一些versioning-aware的方法,通过指定相应的版本ID来获取该object之前版本的信息。
versionedObject = s3Service.getVersionedObject(finalVersionId, vBucketName, “versioned-object”); String versionedData = ServiceUtils.readInputStreamToString( versionedObject.getDataInputStream(), “UTF-8″); System.out.println(“Data from prior version of deleted document: ” + versionedData); |
列出一个bucket中所有的对象版本信息,每个结果都是一个S3Version或者S3DeleteMarker对象。
BaseVersionOrDeleteMarker[] versions = s3Service.listVersionedObjects(vBucketName, null, null); for (int i = 0; i < versions.length; i++) { System.out.println(versions[i]); } |
指定了前缀:
String versionPrefix = “versioned-object”; versions = s3Service.listVersionedObjects(vBucketName, versionPrefix, null); |
JetS3t提供了一个便利的方法来罗列某一个object的版本信息。
versions = s3Service.getObjectVersions(vBucketName, “versioned-object”); |
所有的S3操作都有相应的versioning-aware方法。
versionedObject = s3Service.getVersionedObjectDetails( finalVersionId, vBucketName, “versioned-object”); // Confirm that S3 returned the versioned object you requested if (!finalVersionId.equals(versionedObject.getVersionId())) { throw new Exception(“Incorrect version!”); } s3Service.copyVersionedObject(finalVersionId, vBucketName, “versioned-object”, “destination-bucket”, new S3Object(“copied-from-version”), false, null, null, null, null); AccessControlList versionedObjectAcl = s3Service.getVersionedObjectAcl(finalVersionId, vBucketName, “versioned-object”); s3Service.putVersionedObjectAcl(finalVersionId, vBucketName, “versioned-object”, versionedObjectAcl); |
删除操作:
s3Service.deleteVersionedObject(finalVersionId, vBucketName, “versioned-object”); // You can easily delete all the versions of an object using one of JetS3t’s multi-threaded services. versions = s3Service.getObjectVersions(vBucketName, “versioned-object”); // Convert version and delete marker objects into versionId strings. String[] versionIds = BaseVersionOrDeleteMarker.toVersionIds(versions); (new S3ServiceSimpleMulti(s3Service)).deleteVersionsOfObject( versionIds, vBucketName, “versioned-object”); |
2.1.10 Multi-Factor Authenticated Delete
S3提供了一些额外的数据保护策略,通过multi-factor认证(MFA)实现。下面的例子就是通过MFA认证来删除object版本信息。
// Require multi-factor authentication to delete versions. s3Service.enableBucketVersioningWithMFA(vBucketName); // Check MFA status for the bucket versioningStatus = s3Service.getBucketVersioningStatus(vBucketName); System.out.println(“Multi-factor auth required to delete versions ? “ + versioningStatus.isMultiFactorAuthDeleteRequired()); |
如果开启了MFA,那么用户必须提供相应的序列号以及认证码才能够删除object的版本信息。
String multiFactorSerialNumber = “#111222333″; String multiFactorAuthCode = “12345678″; s3Service.deleteVersionedObjectWithMFA(finalVersionId, multiFactorSerialNumber, multiFactorAuthCode, vBucketName, “versioned-object”); |
如果开启了MFA,那么必须提供multi-factor相关认证信息来关闭MFA。
s3Service.disableMFAForVersionedBucket(vBucketName, multiFactorSerialNumber, multiFactorAuthCode); |
如果开启了MFA,那么必须提供multi-factor认证信息才能够暂停S3的versioning功能。
s3Service.suspendBucketVersioningWithMFA(vBucketName, multiFactorSerialNumber, multiFactorAuthCode); |
2.2 多线程操作
JetS3t工具箱提供了一些工具(S3ServiceMulti和S3ServiceSimpleMulti),使得用户可以同时操作多个对象。在带宽条件允许下,这些工具可以使得用户更快的完成相应的操作。这些操作可以兼容S3Service提供的任何线程安全的操作,例如JetS3t提供的一些HTTP/REST和SOAP方法。
S3ServiceMutli专为一些有着更高需求的开发人员提供。开发人员可以在图形界面中使用S3ServiceMulti,并且它采用的是事件通知(event-notification)的交互方式,而非传统的方法调用。这也意味着用户在使用S3上传一个大文件时,可以实时监控上传的进度(Cockpit中就使用了该功能)。但是,这些功能会使得整个API变得更复杂。S3ServiceSimpleMulti提供了一个简化的接口,开发人员可以直接使用多线程,而无需额外的操作。下面的例子将描述如何使用S3ServiceSimpleMulti。
2.2.1 Multiple Uploads
首先是创建一个S3ServiceSimpleMulti对象。
// Create a simple multi-threading service based on our existing S3Service S3ServiceSimpleMulti simpleMulti = new S3ServiceSimpleMulti(s3Service); |
为了演示多线程的上传功能,这里创建了一个bucket并将一些对象上传到其中。
// First, create a bucket. S3Bucket bucket = new S3Bucket(awsAccessKey + “.TestMulti”); bucket = s3Service.createBucket(bucket); // Create an array of data objects to upload. S3Object[] objects = new S3Object[5]; objects[0] = new S3Object(bucket, “object1.txt”, “Hello from object 1″); objects[1] = new S3Object(bucket, “object2.txt”, “Hello from object 2″); objects[2] = new S3Object(bucket, “object3.txt”, “Hello from object 3″); objects[3] = new S3Object(bucket, “object4.txt”, “Hello from object 4″); objects[4] = new S3Object(bucket, “object5.txt”, “Hello from object 5″); // Upload multiple objects. S3Object[] createdObjects = simpleMulti.putObjects(bucket, objects); System.out.println(“Uploaded ” + createdObjects.length + ” objects”); // Perform a Details/HEAD query for multiple objects. S3Object[] objectsWithHeadDetails = simpleMulti.getObjectsHeads(bucket, objects); // Print out details about all the objects. System.out.println(“Objects with HEAD Details…”); for (int i = 0; i < objectsWithHeadDetails.length; i++) { System.out.println(objectsWithHeadDetails[i]); } |
2.2.2 Multiple Downloads
JetS3t也提供了多线程的下载服务,但是在使用该功能之前,用户需要准备好这些object存放的位置。
// Create a DownloadPackage for each object, to associate the object with an output file. DownloadPackage[] downloadPackages = new DownloadPackage[5]; downloadPackages[0] = new DownloadPackage(objects[0], new File(objects[0].getKey())); downloadPackages[1] = new DownloadPackage(objects[1], new File(objects[1].getKey())); downloadPackages[2] = new DownloadPackage(objects[2], new File(objects[2].getKey())); downloadPackages[3] = new DownloadPackage(objects[3], new File(objects[3].getKey())); downloadPackages[4] = new DownloadPackage(objects[4], new File(objects[4].getKey())); // Download the objects. simpleMulti.downloadObjects(bucket, downloadPackages); System.out.println(“Downloaded objects to current working directory”); |
2.2.3 Multiple Deletes
多线程的删除。
// Delete multiple objects, then the bucket too. simpleMulti.deleteObjects(bucket, objects); s3Service.deleteBucket(bucket); System.out.println(“Deleted bucket: ” + bucket); |
2.3 高级操作
2.3.1 Managing Metadata
S3Object可以包含一些name/value对的metadata信息。这些metadata信息都存储在S3之中,并且可以通过getObject或getObjectDetails来查看这些信息。如果用户希望为object添加一些metadata,那么在上传object之前就应该这些好这些信息。需要注意的是这些metadata的name不能有空格。
S3Object objectWithMetadata = new S3Object(“metadataObject”); objectWithMetadata.addMetadata(“favourite-colour”, “blue”); objectWithMetadata.addMetadata(“document-version”, “0.3″); |
2.3.2 Securing Your AWS Credentials
用户应该保管好自己的AWS账户信息,这些信息都是用来登录以及管理S3账户。JetS3t将这些信息保存在AWSCredentials对象中,AWSCredentials提供了一些方法将这些账户信息加密之后保存在文件中。
// Save credentials to an encrypted file protected with a password. File credFile = new File(“awscredentials.enc”); awsCredentials.save(“password”, credFile); // Load encrypted credentials from a file. AWSCredentials loadedCredentials = AWSCredentials.load(“password”, credFile); System.out.println(“AWS Key loaded from file: ” + loadedCredentials.getAccessKey()); // You won’t get far if you use the wrong password… try { loadedCredentials = AWSCredentials.load(“wrongPassword”, credFile); } catch (S3ServiceException e) { System.err.println(“Cannot load credentials from file with the wrong password!”); } |
2.3.3 Access Control
S3使用Access Control Lists来管理buckets和objects的访问信息。在默认配置中,用户创建的任何bucket或object都属于该用户本人,也只有该用户才有权限访问。但是,用户可以通过一些设置使得一些buckets或objects能够被其他人访问。有关于这些权限可以参考Amazon的ACL协议。下列的代码展示了使用ACL协议来管理bucket或object访问权限的方法。
// Create a bucket in S3. S3Bucket publicBucket = new S3Bucket(awsAccessKey + “.publicBucket”); s3Service.createBucket(publicBucket); // Retrieve the bucket’s ACL and modify it to grant public access, // ie READ access to the ALL_USERS group. AccessControlList bucketAcl = s3Service.getBucketAcl(publicBucket); bucketAcl.grantPermission(GroupGrantee.ALL_USERS, Permission.PERMISSION_READ); // Update the bucket’s ACL. Now anyone can view the list of objects in this bucket. publicBucket.setAcl(bucketAcl); s3Service.putBucketAcl(publicBucket); System.out.println(“View bucket’s object listing here: http://s3.amazonaws.com/” + publicBucket.getName()); |
2.3.4 Temporary Public URLs
用户可以通过某个URL地址来访问S3中的某个object,这个URL地址是有时效的。
// Create a private object in S3. S3Bucket privateBucket = new S3Bucket(“privateBucket”); S3Object privateObject = new S3Object( privateBucket, “privateObject.txt”, “This object is private”); s3Service.createBucket(privateBucket); s3Service.putObject(privateBucket, privateObject); // Determine what the time will be in 5 minutes. Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, 5); Date expiryDate = cal.getTime(); String signedUrl = S3Service.createSignedGetUrl(privateBucket.getName(), privateObject.getKey(), awsCredentials, expiryDate); System.out.println(“Signed URL: ” + signedUrl); |
2.3.5 S3 POST Forms
当创建一个S3的POST form时,那么通过浏览器访问该网页的其它用户都可以上传文件到S3账户中,不需要安装任何S3的客户端软件。更多信息请参照S3 POST[4]相关文档。
在这里我们将创建一个不涉及任何policy的POST form,这也意味着这个form不会失效,也不会有其它的限制条件。当且仅当目标bucket开放了写权限,这个窗口才可以工作。
String unrestrictedForm = S3Service.buildPostForm(“public-bucket”, “${filename}”); |
为了使用这个form,那么将它保存成UTF-8编码的html文件,然后通过浏览器打开即可。接下来我们将创建一系列带有约束条件的POST form,允许用户上传图像文件到一个受保护的bucket之中。上传成功后,将用户转到另外一个页面上。
String bucketName = “test-bucket”; String key = “uploads/images/pic.jpg”; String[] inputFields = new String[] { “<input type=\”hidden\” name=\”acl\” value=\”public-read\”>”, “<input type=\”hidden\” name=\”Content-Type\” value=\”image/jpeg\”>”, “<input type=\”hidden\” name=\”success_action_redirect\” value=\”http://localhost/post_upload\”>” }; |
需要说明的是所有的POST请求都会被强制的加上bucket和key的值。除了这两个强制的值之外,我们还可以加上一个field用来控制上传文件的大小。
String[] conditions = { S3Service.generatePostPolicyCondition_Equality(“bucket”, bucketName), S3Service.generatePostPolicyCondition_Equality(“key”, key), S3Service.generatePostPolicyCondition_Range(10240, 204800), // Conditions to allow the additional fields specified above S3Service.generatePostPolicyCondition_Equality(“acl”, “public-read”), S3Service.generatePostPolicyCondition_Equality(“Content-Type”, “image/jpeg”), S3Service.generatePostPolicyCondition_Equality(“success_action_redirect”, “http://localhost/post_upload”) }; // Form will expire in 24 hours cal = Calendar.getInstance(); cal.add(Calendar.HOUR, 24); Date expiration = cal.getTime(); // Generate the form. String restrictedForm = S3Service.buildPostForm( bucketName, key, awsCredentials, expiration, conditions, inputFields, null, true); |
2.3.6 Activate Requester Pays for a bucket
在S3的默认配置中,一个bucket的所有上传下载等操作产生的费用都由这个bucket所属的用户来支付。S3的Requester Pays特性允许用户将自己的bucket配置成请求者支付模式,即请求和传输的费用由每个requester来承担。需要说明的是,只有S3的REST API支持Requester Pays,因此在编写代码时必须使用RestS3Service,而不是SoapS3Service。
// Set a bucket to be Requester Pays s3Service.setRequesterPaysBucket(bucketName, true); // Set a bucket to be Owner pays (the default value for S3 buckets) s3Service.setRequesterPaysBucket(bucketName, false); // Find out whether a bucket is configured as Requester pays s3Service.isRequesterPaysBucket(bucketName); |
2.3.7 Access a Requester Pays bucket
当一个bucket设置成Requester Pays模式时,AWS的其它用户在满足以下两个条件后就可以上传/下载该bucket中的文件:有ACL的相应权限;愿意承担相关操作的费用。通过设置标签位RequesterPaysEnabled来使用Requester Pays相关的操作。JetS3t的默认配置设置RequesterPaysEnabled为false:httpclient.requester-pays-buckets-enabled=false。
s3Service.setRequesterPaysEnabled(true); |
用户在操作一个Requester Pays的bucket时可以生成一个URL地址,允许第三方用户访问该bucket中的一些对象。
// Generate a signed GET URL for Map httpHeaders = null; long expirySecsAfterEpoch = System.currentTimeMillis() / 1000 + 300; boolean isVirtualHost = false; boolean isHttpsUrl = false; String requesterPaysSignedGetUrl = S3Service.createSignedUrl(“GET”, bucketName, “object-name”, Constants.REQUESTER_PAYS_BUCKET_FLAG, // Include Requester Pays flag httpHeaders, awsCredentials, expirySecsAfterEpoch, isVirtualHost, isHttpsUrl); |
2.3.8 Amazon DevPay S3 Accounts
Amazon的DevPay服务允许一些代理出售user-pays的S3账户。为了访问DevPay产品中的S3账户,JetS3t需要添加一些额外的账户信息,包括DevPay User Token和DevPay Product Token。
AWSDevPayCredentials devPayCredentials = new AWSDevPayCredentials( “YOUR_AWS_ACCESSS_KEY”, “YOUR_AWS_SECRET_KEY”, “DEVPAY_USER_TOKEN”, “DEVPAY_PRODUCT_TOKEN”); |
一旦设置好这些信息,那么用户就可以直接操作DevPay账户。
S3Service devPayService = new RestS3Service(devPayCredentials); devPayService.listAllBuckets(); |
同样也可以为DevPay S3账户创建一些URL地址。
cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, 5); String signedDevPayUrl = S3Service.createSignedGetUrl( “devpay-bucket-name”, “devpay-object-name”, devPayCredentials, cal.getTime()); |
[1] http://jets3t.s3.amazonaws.com/index.html
[3] http://www.amazon.com/cloudfront
[4] http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingHTTPPOST.html