这里是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
。
我需要完成几件事:
Array<String>
或Scala Array[String]
)的数组/映射/数据结构,其中包含ID目录的所有字母数字ID(因此元素0为"3dj439fj9fj49j"
,元素1为"3eidi04d40d40d"
等);和Array<Date>
或Scala Array[Date]
)的数组/地图/数据结构,其中包含每个ID目录对应文件的最后修改时间戳data.json
。因此,如果mybucket/3dj439fj9fj49j/data.json
具有上次修改的日期/时间戳,例如2017-05-29 11:19:24T,则该datetime将是第二个数组的第一个元素my-bucket
4个元素,并在下面获得第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代码联系在一起的示例。
> 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] 删除。
我来说两句