【问题标题】:Android HttpURLConnection PUT to Amazon AWS S3 403 errorAndroid HttpURLConnection PUT 到 Amazon AWS S3 403 错误
【发布时间】:2013-03-16 14:33:16
【问题描述】:

使用具有签名、过期和访问密钥的预签名 URL 将文件上传到 Amazon S3,使用以下代码我可以使用普通 java 代码上传文件,但 Android 中的相同代码给我 403 错误。 Presigned 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 库中添加到幕后的 Header-parameters 的?

【问题讨论】:

  • 你有什么解决办法吗??@Mayank
  • 我也有同样的问题,请问您有解决办法吗?

标签: java android amazon-s3 httpurlconnection put


【解决方案1】:

您使用的是AWS SDK for Android 吗?它有正确的 API,我怀疑使用它上传到 S3 会更容易,而且更安全。我相信他们那里也有教程、代码示例和演示。

还有一个API for S3 和您可能需要的其他课程。 PutObjectRequest 将帮助您从手机客户端上传文件,对您的情况很有用。

【讨论】:

  • 为了限制应用程序的大小,我避免在设备上使用 SDK,并且我不想将 SDK 用于该操作。
【解决方案2】:

所以经过一些尝试/错误/搜索后发现了问题:

虽然创建预签名 URL 时指定 Content-Type(基于您的数据)很重要,否则您将不断收到 403 Signature don't match,您在此处指定的 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");

检查这个bug,最新的SDK应该让你设置Content-Type

【讨论】:

  • 不...这对我不起作用...我可以使用从 mac os 运行的 JAVA 客户端上传。但是,使用相同的 url 我收到 403 错误。这意味着Android环境与mac os不同。
【解决方案3】:

生成网址的方式:

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();
}

【讨论】:

    【解决方案4】:

    请像这样设置您的内容类型:

    connection.setRequestProperty("Content-Type"," ");
    

    因为默认为 HttpsUrlConnection 自动生成内容类型为:

    "Content-Type: application/x-www-form-urlencoded"
    

    这会导致签名不匹配。

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题。这就是我遇到它的原因:

      预签名 URL 可让您访问 URL 中标识的对象, 前提是预签名 URL 的创建者有权 访问该对象。也就是说,如果您收到要上传的预签名 URL 对象,您可以仅在对象的创建者 预签名 URL 具有上传该对象的必要权限。

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

      一旦我授予我的 lambda 函数 PutObject 对该 s3 存储桶的权限,它就可以工作了!

      【讨论】:

        猜你喜欢
        • 2019-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-10
        • 2018-06-01
        • 2015-11-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多