4

次のコードを使用して、署名、有効期限、AccessKey を持つ署名付き URL を使用してファイルを Amazon S3 にアップロードすると、通常の Java コードを使用してファイルをアップロードできますが、Android で同じコードを使用すると 403 エラーが発生します。署名付き URL は Amazon SDK を使用して生成されます

http://developer.android.com/reference/java/net/HttpURLConnection.htmlhttp://android-developers.blogspot.com/2011/09/androids-http-clients.htmlを読みましたが、できませんどのヘッダーパラメーターを使用する必要があるかを把握します。Androidでは、サーバーが拒否するリクエストにヘッダーを設定していると思います

    HttpURLConnection connection=(HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("PUT"); 
    OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
    out.write("This text uploaded as object.");
    out.close();
    int responseCode = connection.getResponseCode();

例外: 403; 署名が一致しません:-o

誰かがこの問題に遭遇しましたか? または、Android ライブラリの舞台裏でどのヘッダー パラメータが追加されるかについて、さらに詳しく教えてください。

4

5 に答える 5

2

したがって、いくつかの試行錯誤/検索の後、問題が見つかりました:

署名付き URL を作成することは (データに基づいて) Content-Type を指定することが重要ですが、そうしないと 403 署名が一致しません。ここで指定する contentType は HttpURLConnection 接続オブジェクトで言及する必要があります。

    string s3url = s3Client.GetPreSignedURL(new GetPreSignedUrlRequest()
                   .WithBucketName(bucketName)
                   .WithKey(keyName)
                   .WithContentType("application/octet-stream") // IMPORTANT
                   .WithVerb(HttpVerb.PUT)
                   .WithExpires(<YOUR EXPIRATION TIME>);

接続内..これを問題のコードに追加します(「PUT」)

    connection.setFixedLengthStreamingMode(< YOUR DATA.LENGTH ?>);        
    connection.setRequestProperty("Content-Type","application/octet-stream");

このバグを確認してください。最新の SDK では Content-Type を設定できるはずです

于 2013-03-27T16:24:06.600 に答える
1

URL を生成する方法:

private static URL generateRUL(String objectKey, String ACCESS_KEY, String SECRET_KEY, String BUCKET_NAME) {
    AmazonS3 s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
    URL url = null;

    try {
        GeneratePresignedUrlRequest request  = new GeneratePresignedUrlRequest(BUCKET_NAME, objectKey);
        request.setMethod(com.amazonaws.HttpMethod.PUT);
        request.setExpiration(new Date( System.currentTimeMillis() + (60 * 60 * 1000)));

        // Very important ! It won't work without adding this! 
        // And request.addRequestParameter("Content-Type", "application/octet-stream") won't work neither
        request.setContentType("application/octet-stream");

        url = s3Client.generatePresignedUrl(request ); 
    } catch (AmazonServiceException exception) { 
    } catch (AmazonClientException ace) { }

    return url;
}

ファイルをアップロードする方法:

public int upload(byte[] fileBytes, URL url) {
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("PUT");
    connection.setRequestProperty("Content-Type", "application/octet-stream"); // Very important ! It won't work without adding this!
    OutputStream output = connection.getOutputStream();

    InputStream input = new ByteArrayInputStream(fileBytes);
    byte[] buffer = new byte[4096];
    int length;
    while ((length = input.read(buffer)) > 0) {
        output.write(buffer, 0, length);
    }
    output.flush();

    return connection.getResponseCode();
}
于 2015-03-28T09:38:48.250 に答える
0

私はこれと同じ問題を抱えていました。私がそれに直面した理由は次のとおりです。

署名付き URL の作成者がそのオブジェクトへのアクセス許可を持っている場合、署名付き URL を使用すると、URL で識別されたオブジェクトにアクセスできます。つまり、オブジェクトをアップロードするための署名付き URL を受け取った場合、署名付き URLの作成者がそのオブジェクトをアップロードするために必要な権限を持っている場合にのみ、オブジェクトをアップロードできます。

http://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html

その s3 バケットに対するラムダ関数の PutObject 権限を付与すると、機能しました。

于 2016-10-12T04:58:45.133 に答える
0

AWS SDK for Androidを使用していますか? それには正しいAPIがあり、それを使用してS3にアップロードする方が簡単で、より安全になると思います. チュートリアル、コード サンプル、デモもあると思います。

S3 用のAPIやその他の必要なクラスもあります。PutObjectRequestは、電話クライアントからファイルをアップロードするのに役立ち、あなたの場合に役立ちます。

于 2013-03-26T17:09:53.017 に答える