【问题标题】:Unable to listObjects from GCS bucket无法列出 GCS 存储桶中的对象
【发布时间】:2019-01-10 04:20:47
【问题描述】:

我正在尝试使用最新的 aws-sdk java 库从 GCS 存储桶中列出对象。

这里参考代码sn-p

ClientConfiguration clientConfiguration = new ClientConfiguration();
  // Solution is update the Signer Version. 
  clientConfiguration.setSignerOverride("S3SignerType"); 

  AWSCredentials awsCredentials = new BasicAWSCredentials("XXX","XXX");
  AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard()
    .withCredentials(new  AWSStaticCredentialsProvider(awsCredentials))
    .withClientConfiguration(clientConfiguration)
    .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("https://storage.googleapis.com","Multi-Regional")).build();

  String bucketName = "bucket_name";

  // List Objects 
  amazonS3Client.listObject(bucketName);

但接收到无效参数。请参阅错误和调试日志 我也可以使用上面的 amazonS3Client 处理 getObjects 和 putObjects。 有什么想法吗?

2017-11-13 17:54:15,360 [main] DEBUG com.amazonaws.request - Sending Request: GET https://bucket_name.storage.googleapis.com / Parameters: ({"encoding-type":["url"]}Headers: (User-Agent: aws-sdk-java/1.11.158 Linux/4.10.0-38-generic Java_HotSpot(TM)_64-Bit_Server_VM/25.131-b11/1.8.0_131, amz-sdk-invocation-id: 121cd76e-1374-4e5d-9e68-be22ee2ad17a, Content-Type: application/octet-stream, ) 
2017-11-13 17:54:16,316 [main] DEBUG com.amazonaws.request - Received error response: com.amazonaws.services.s3.model.AmazonS3Exception: Invalid argument. (Service: Amazon S3; Status Code: 400; Error Code: InvalidArgument; Request ID: null), S3 Extended Request ID: null
Exception in thread "main" com.amazonaws.services.s3.model.AmazonS3Exception: Invalid argument. (Service: Amazon S3; Status Code: 400; Error Code: InvalidArgument; Request ID: null), S3 Extended Request ID: null
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1588)
        at 

【问题讨论】:

  • GCS 实际上支持模拟 S3 REST API。
  • 我认为最好使用云提供商特定的 CLI 来实现长期可持续性。

标签: amazon-web-services amazon-s3 google-cloud-platform google-cloud-storage aws-sdk


【解决方案1】:

S3 对其对象列表调用有一个名为“encodingtype”的参数,当设置为“url”时,使用 URL 编码对无法在 XML 1.0 中本地呈现的字符进行编码。客户端库似乎正在使用该标志。我不相信 GCS 的 XML API 支持该参数,因此调用将失败并出现 InvalidArgument 错误。

您可以通过使用ListObjectRequest 并调用setEncodingType(null) 来避免这种情况,尽管我没有尝试过。

【讨论】:

  • 即使在将“encodingType”设置为 null 之后,ListObjectRequest 也会在其查询参数中添加默认的“url”。所以我仍然收到相同的“无效查询参数编码类型”错误。是否可以在使用 AmazonHttpClient 使用任何处理程序或侦听器执行请求之前从请求中删除此参数。
【解决方案2】:

我在同一条船上,但使用的是 aws-sdk php 库。我将问题追溯到 S3Client 类的构造函数,其中添加了一堆中间件,其中一个是设置编码类型。注释掉这一行可以让我成功执行请求,所以我知道我在正确的轨道上。

$stack->appendSign(PutObjectUrlMiddleware::wrap(), 's3.put_object_url');
$stack->appendSign(PermanentRedirectMiddleware::wrap(), 's3.permanent_redirect');
$stack->appendInit(Middleware::sourceFile($this->getApi()), 's3.source_file');
$stack->appendInit($this->getSaveAsParameter(), 's3.save_as');
$stack->appendInit($this->getLocationConstraintMiddleware(), 's3.location');
// $stack->appendInit($this->getEncodingTypeMiddleware(), 's3.auto_encode');
$stack->appendInit($this->getHeadObjectMiddleware(), 's3.head_object');

看看aws-sdk for java是否至少给了你一些有条件地应用中间件的选项,但它似乎与php版本无关。

【讨论】:

    【解决方案3】:

    正如 Brandon 和 Pez 所注意到的,GCS 不喜欢 S3Client 本地添加的 EncodingType 标头。

    幸运的是,使用中间件可以轻松解决此问题。这避免了通常应该避免的对供应商文件夹的编辑。

    use Aws\Middleware;
    
    $client = new S3Client([
        'credentials' => [
            'key' => 'XXXX',
            'secret' => 'YYYY'
        ],
        'region' => 'europe',
        'endpoint' => 'https://storage.googleapis.com',
        'version' => 'latest'
    ]);
    
    $middleware = Middleware::tap(function ($command, $request = null) {
         unset($command['EncodingType']);
    });
    
    $client->getHandlerList()->appendInit($middleware, 'encode-type-interceptor');
    

    另请参阅:https://blog.bandhosting.nl/blog/avoid-listobjects-invalid-query-parameter-s-encoding-type-errors-when-using-s3-with-google-cloud-storage

    【讨论】:

    • 请在您的答案中包含代码,而不是您博客的链接,或者除了链接之外。
    • 当然,没问题
    【解决方案4】:

    我遇到了同样的问题,发现 Amazon Java API 在 S3 调用期间包含几个挂钩,可用于从 HTTP 请求中删除编码类型。

    {
      return AmazonS3ClientBuilder.standard()//
           .withCredentials(getAwsCredentialsProvider())//
           .withEndpointConfiguration(getEndpointConfiguration(regionName))//
           .withRequestHandlers(new GoogleRequestHandler()) // IMPORTANT PART
           .build();
    }
    
    public class GoogleRequestHandler extends RequestHandler2 {
    
        @Override
        public void beforeRequest(Request<?> request) {
            // google does not support the encoding-type parameter so just remove it from the request
            // This appears to be only true for ListObjects
            if (request.getOriginalRequest() instanceof ListObjectsRequest) {
                Map<String, List<String>> params = request.getParameters();
                params.remove("encoding-type");
            }
        }
    }
    

    有关更多文档,请参阅 RequestHandler2

    【讨论】:

      猜你喜欢
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 2021-10-22
      • 2021-10-24
      • 2015-08-18
      • 2021-02-23
      相关资源
      最近更新 更多