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

标签 scala amazon-s3 java-client

这里是 Scala 2.11,尽管这涉及 AWS S3 Java client API所以这真的是一个 Java 问题。如果有人能在 Scala 中提供答案,那将是很棒的,但我很高兴接受任何有效的 Java 答案(我总是可以在我自己的时间用 Scala 化它).


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

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

因此,存储桶下的每个直接子对象都是一个具有字母数字名称的目录。我将这些称为“ID 目录”。这些 ID 目录中的每一个都有一个全部名为data.json 的子对象。 .

我需要完成几件事:

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

这些不一定必须是数组,它们可以是映射、元组等。如上所述,我只需要 1+ 个数据结构来保存此内容。

来自lib's 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)

解释

首先,我们有一些 Bootstrap 来设置凭据和创建客户端。然后,我们发出 listObjects,这会触发对 S3 服务的调用。我们将这些结果过滤为仅以“data.json”结尾的键。然后,我们将结果映射到由父路径名和对象的最后修改日期/时间组成的元组。为了确定父路径,我们在路径分隔符上split 并检索先前的路径组件。作为一种特殊情况,如果文件位于根目录中,则我们称其父级为 "/"

我选择将结果表示为元组,但如果您愿意,可以将其更改为其他数据结构。

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

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

关于scala - 使用 AWS S3 Java 客户端获取目录和对象元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45444653/

相关文章:

amazon-s3 - 使用 Airflow 将数据从 Redshift 卸载到 S3

java - 如何从java客户端调用MCollective

java - 安卓手机: How to simply open an application without installation (as it is already installed) using Appium

scala - java.io.Serialized 和 GenTraversableOnce 类型不匹配

scala - 如何处理 Spark 和 Scala 中的异常

amazon-web-services - 具有多个AWS凭证配置文件的PySpark s3访问?

asp.net - 使用 ASP .Net 创建指向 S3 或 Cloudfront 托管内容的过期链接

java - Android SignalR java 客户端 : Not receiving all the SignalR messages on the HubConnection

scala - 模式匹配与专门的 Scala

scala - 如何在sbt-build docker镜像中提升特权