S3 / Cloudfront:如何在存储桶中列出文件夹的内容

时间:2016-07-18 01:01:16

标签: amazon-web-services amazon-s3 salesforce apex

我写了一个方法来签署URL以读取通过Cloudfront访问的S3存储桶:

private HTTPResponse signURL(String endpoint) {
    String keyPairId = 'keyPairId';
    String secret    = 'SOME_SECRET';
    String method    = 'GET';
    Datetime dt      = Datetime.now();
    Long l           = dt.getTime();
    Long expiryLong  = (l / 1000) + 3600;
    String expiry    = String.valueOf(expiryLong);
    String policy    = policy('http://' + cfhost + '/' + endpoint, expiry);
    String policyEnc = EncodingUtil.base64Encode(Blob.valueOf(policy));
    String rPolicy   = cfReplace(policyEnc);
    Blob mac         = Crypto.generateMac('HMACSHA1',
                                          Blob.valueOf(rPolicy),
                                          Blob.valueOf(secret));
    String signature = cfReplace(EncodingUtil.base64Encode(mac));

    HttpRequest req = new HttpRequest();
    req.setMethod(method);
    req.setEndpoint('http://' + cfhost + '/' + endpoint + '?Policy=' +
        policyEnc + '&Signature=' + signature + '&Key-Pair-Id=' +
        keyPairId);

    Http http = new Http();
    HTTPResponse res = http.send(req);
    return res;
}

现在,如果端点设置为'',我的方法可以正常工作。如果我将文件夹名称放在端点中(如00Q17000008LRcAEAW/*),我会在XML响应中收到一堆错误。

XMLNode[ELEMENT,Error,null,null,null,[XMLNode[ELEMENT,Code,null,null,null,[XMLNode[TEXT,null,null,null,null,null,NoSuchKey,]],null,], XMLNode[ELEMENT,Message,null,null,null,[XMLNode[TEXT,null,null,null,null,null,The specified key does not exist.,]],null,], XMLNode[ELEMENT,Key,null,null,null,[XMLNode[TEXT,null,null,null,null,null,00Q17000008LRcAEAW/*,]],null,], XMLNode[ELEMENT,RequestId,null,null,null,[XMLNode[TEXT,null,null,null,null,null,some_req_id,]],null,], XMLNode[ELEMENT,HostId,null,null,null,[XMLNode[TEXT,null,null,null,null,null,some_host_id,]],null,]],null,]

我无法列出整个存储桶,因为它对于1000键限制来说太大了。如何列出文件夹?

1 个答案:

答案 0 :(得分:1)

有关S3的预期,请参阅列表对象的S3文档,V1V2

简而言之,您必须在查询字符串中提供前缀和分隔符(几乎总是/),而不是路径。对于对象列表,路径始终是存储桶的根,例如:

https://dxxxexample.cloudfront.net/?delimiter=/&prefix=00Q17000008LRcAEAW/&...

这也意味着如果您为分发定义了default root object,则无法通过分发来提取目录列表。在这种情况下,您需要第二次分发,或者您需要直接从S3获取对象列表。

无论如何,请记住,对象列表相对昂贵,超过GET请求价格的10倍,因此如果缓存响应有意义,使用CloudFront获取它们可能有意义,或者您可能对于对象列表,我想做一些完全不同的事情。我一直在推出使用S3事件通知,Lambda和RDS的设置,将所有对象及其元数据存储在一个单独的近实时数据库中,在那里我可以获得更快,更完整的列表而无需成本(和我可以根据元数据搜索对象。