使用AWS S3 Java客户端获取目录和对象元数据

me

这里是Scala 2.11,尽管这与AWS S3 Java客户端API有关,所以这实际上是一个Java问题。如果有人可以在Scala中提供答案,那将是非常棒的,但是我会很乐意接受任何可行的Java答案(我总是可以自己自行对它进行Scala化)。


我正在尝试使用AWS S3客户端库连接到S3上的存储桶,该存储桶下面是以下目录结构:

my-bucket/
    3dj439fj9fj49j/
        data.json
    3eidi04d40d40d/
        data.json
    a874739sjsww93/
        data.json
    ...

因此,存储桶下的每个直接子对象都是带有字母数字名称的目录。我将这些称为“ ID目录”。并且每个ID目录均包含一个子对象的所有命名data.json

我需要完成几件事:

  1. 我需要一个字符串(JavaArray<String>或Scala Array[String]的数组/映射/数据结构,其中包含ID目录的所有字母数字ID(因此元素0为"3dj439fj9fj49j",元素1为"3eidi04d40d40d"等);
  2. 我需要一个日期(JavaArray<Date>或Scala Array[Date]的数组/地图/数据结构,其中包含每个ID目录对应文件最后修改时间戳data.json因此,如果mybucket/3dj439fj9fj49j/data.json具有上次修改的日期/时间戳,例如2017-05-29 11:19:24T,则该datetime将是第二个数组的第一个元素
  3. 这两个数组/地图/数据结构需要关联,这意味着我可以访问第一个(ID)数组的第my-bucket4个元素,并在下面获得第5个ID目录,并且我还可以访问第2个(日期和日期)的第4个元素)数组并获取第5个ID目录的data.json子对象的最后修改时间戳

这些不一定是数组,它们可以是地图,元组等。我只需要1个以上的数据结构来保存此内容,如上所述。

lib的Javadocs中,我看到了一个ObjectMetadata#getLastModified字段,但是看不到用于读取给定的父目录路径S3Object(意味着data.json的父ID目录)的任何内容。总而言之,我最大的尝试就是失败了:

val s3Client = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey))
val bucketRoot : S3Object = s3Client.getObject("myBucket","/")

// TODO: How to query 'bucketRoot' for all its child ID directories?
val idDirs : Array[S3Object] = ???

var dataMap : Map[String,Date] = null
idDirs.foreach(idDir ->
  // TODO: getName() and getChildSomehow() don't exist...obviously
  dataMap :+ idDir.getName() -> idDir.getChildSomehow("data.json").getObjectMetadata.getLastModified
)

那里有任何S3 API专家可以发现我哪里出问题了,或者在这里向正确的方向推我吗?提前致谢!

克里斯·诺罗斯

您可以调用AmazonS3#listObjects(String)以获取存储桶中的对象列表。响应将为S3ObjectSummary找到的每个键包含一个您可以致电S3ObjectSummary#getLastModified()获取上次修改的日期/时间。

这是一个将所有内容与一些Scala代码联系在一起的示例。

来自S3存储桶的输入

> aws s3 ls --recursive s3://<REDACTED>/
2017-08-02 13:45:12          0 3dj439fj9fj49j/
2017-08-02 13:45:28          0 3dj439fj9fj49j/data.json
2017-08-02 13:45:16          0 3eidi04d40d40d/
2017-08-02 13:45:33          0 3eidi04d40d40d/data.json
2017-08-02 13:45:19          0 a874739sjsww93/
2017-08-02 13:45:37          0 a874739sjsww93/data.json

import collection.JavaConverters._

import com.amazonaws.auth.AWSStaticCredentialsProvider
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3ClientBuilder

val key = <REDACTED>
val secret = <REDACTED>
val bucketName = <REDACTED>
val region = <REDACTED>

val creds = new BasicAWSCredentials(key, secret)
val s3 = AmazonS3ClientBuilder.standard.withCredentials(new AWSStaticCredentialsProvider(creds)).withRegion(region).build

val objectSummaries = s3.listObjects(bucketName).getObjectSummaries.asScala
val dataFiles = objectSummaries.filter { _.getKey.endsWith("data.json") }
val dataDirectories = dataFiles.map(dataFile => {
  val keyComponents = dataFile.getKey.split("/")
  val parent = if (keyComponents.length > 1) keyComponents(keyComponents.length - 2) else "/"
  (parent, dataFile.getLastModified)
})
dataDirectories.foreach(println)

输出量

(3dj439fj9fj49j,Wed Aug 02 13:45:28 PDT 2017)
(3eidi04d40d40d,Wed Aug 02 13:45:33 PDT 2017)
(a874739sjsww93,Wed Aug 02 13:45:37 PDT 2017)

说明

首先,我们有一些引导程序来设置凭据并创建客户端。然后,我们发出listObjects,这会触发对S3服务的调用。我们将filter这些结果只包含以“ data.json”结尾的键。然后,我们map将结果转换为元组,该元组由父路径名和对象的最后修改日期/时间组成。为了确定父路径,我们split在路径分隔符上并检索先前的路径组件。作为特殊情况,如果文件位于根目录中,那么我们说它的父目录是"/"

我选择将结果表示为元组,但可以根据需要将其更改为其他数据结构。

请注意,对于包含大量对象的存储桶,您可能要使用它AmazonS3#listObjects(String, String)来代替,以便可以将返回的结果限制为与特定前缀匹配的键。这将减少响应消耗的网络带宽量以及响应数据所需的处理量。

要获得更多选择,您还可以考虑AmazonS3#listObjects(ListObjectsRequest)AmazonS3#listObjectsV2(ListObjectsV2Request)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章