使用HTTP POST上传文件到S3存储桶

3
我正在开发一个应用程序,将利用亚马逊的S3存储。尽管我已经按照亚马逊提供的教程和示例进行操作,但仍无法使上传功能正常运行。我一直收到以下提示信息:The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256. 存储桶名为testbucket-10.09.2017,位于Frankfurt (eu-central-1)地区。我甚至找到了一个应用程序声称可以实现我需要的功能,但错误消息仍相同。下面的代码主要来自AWS提供的文档和教程,并经过了修改。非常感谢您的帮助。
我使用的代码如下:
我的 HTML 表单:
<html> 
  <head>
    <title>S3 POST Form</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>

  <body> 
    <form action="https://testbucket-10.09.2017.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
      <input type="hidden" name="key" value="uploads/${filename}">
      <input type="hidden" name="AWSAccessKeyId" value="REMOVED FOR SAFETY"> 
      <input type="hidden" name="acl" value="private"> 
      <input type="hidden" name="success_action_redirect" value="http://localhost/">
      <input type="hidden" name="policy" value="ZXlKbGVIQnBjbUYwYVc5dUlqb2dJakl3TVRndE1ERXRNREZVTURBNk1EQTZNREJhSWl3S0lDQWlZMjl1WkdsMGFXOXVjeUk2SUZzZ0NpQWdJQ0I3SW1KMVkydGxkQ0k2SUNKMFpYTjBZblZqYTJWMExURXdMakE1TGpJd01UY2lmU3dnQ2lBZ0lDQmJJbk4wWVhKMGN5MTNhWFJvSWl3Z0lpUnJaWGtpTENBaWRYQnNiMkZrY3k4aVhTd0tJQ0FnSUhzaVlXTnNJam9nSW5CeWFYWmhkR1VpZlN3S0lDQWdJSHNpYzNWalkyVnpjMTloWTNScGIyNWZjbVZrYVhKbFkzUWlPaUFpYUhSMGNEb3ZMMnh2WTJGc2FHOXpkQzhpZlN3S0lDQWdJRnNpYzNSaGNuUnpMWGRwZEdnaUxDQWlKRU52Ym5SbGJuUXRWSGx3WlNJc0lDSWlYU3dLSUNBZ0lGc2lZMjl1ZEdWdWRDMXNaVzVuZEdndGNtRnVaMlVpTENBd0xDQXhNRFE0TlRjMlhRb2dJRjBLZlE9PQ==">
      <input type="hidden" name="signature" value="REMOVED FOR SAFETY">
      <input type="hidden" name="Content-Type" value="image/jpeg">
      <!-- Include any additional input fields here -->

      File to upload to S3: 
      <input name="file" type="file"> 
      <br> 
      <input type="submit" value="Upload File to S3"> 
    </form> 
  </body>
</html>

我的Java代码生成策略和签名:

public static void myAttempt() throws Exception {

        String policy_document = constructPolicy();
        String aws_secret_key="REMOVED FOR SAFETY";

        String policy = (new BASE64Encoder()).encode(
                policy_document.getBytes("UTF-8")).replaceAll("\n","").replaceAll("\r","");

        String dateStamp ="20170912";
        String region = "eu-central-1";
        String serviceName ="s3";
        System.out.println("NEW SIGNATURE: "+getSignature(getSignatureKey(aws_secret_key,dateStamp,region,serviceName)));

        System.out.println("ENCODED POLICY: "+policy);        
    }

private static String constructPolicy() throws UnsupportedEncodingException {

        String policy_document="{\"expiration\": \"2018-01-01T00:00:00Z\",\n" +
                "  \"conditions\": [ \n" +
                "    {\"bucket\": \"testbucket-10.09.2017\"}, \n" +
                "    [\"starts-with\", \"$key\", \"uploads/\"],\n" +
                "    {\"acl\": \"private\"},\n" +
                "    {\"success_action_redirect\": \"http://localhost/\"},\n" +
                "    [\"starts-with\", \"$Content-Type\", \"\"],\n" +
                "    [\"content-length-range\", 0, 1048576]\n" +
                "  ]\n" +
                "}";

        String policy = (new BASE64Encoder()).encode(
                policy_document.getBytes("UTF-8")).replaceAll("\n","").replaceAll("\r","");
        return policy;
    }

private static byte[] HmacSHA256(String data, byte[] key) throws Exception {
        String algorithm="HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF8"));
    }

private static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception  {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF8");
        byte[] kDate    = HmacSHA256(dateStamp, kSecret);
        byte[] kRegion  = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256("aws4_request", kService);
        return kSigning;
    }

private static String getSignature(byte[] key) throws Exception{

        return base16().lowerCase().encode(HmacSHA256(constructPolicy(), key));
    }

4
除非你有非常充分的理由需要直接使用API,否则我建议使用Java AWS SDK - wkl
你是指将文件发送到后端(Java)然后从那里上传吗? - Syn
1个回答

3

事实证明,当进行搜索时,过时的AWS文档和示例通常是最先显示的结果之一。几页谷歌搜索结果后,出现了一个更新的示例。基本上,我使用的表格是错误的。正确的表格如下:

<html>
  <head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  </head>
  <body>

  <form action="http://sigv4examplebucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
    Key to upload: 
    <input type="input"  name="key" value="user/user1/${filename}" /><br />
    <input type="hidden" name="acl" value="public-read" />
    <input type="hidden" name="success_action_redirect" value="http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html" />
    Content-Type: 
    <input type="input"  name="Content-Type" value="image/jpeg" /><br />
    <input type="hidden" name="x-amz-meta-uuid" value="14365123651274" /> 
    <input type="hidden" name="x-amz-server-side-encryption" value="AES256" /> 
    <input type="text"   name="X-Amz-Credential" value="AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request" />
    <input type="text"   name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
    <input type="text"   name="X-Amz-Date" value="20151229T000000Z" />

    Tags for File: 
    <input type="input"  name="x-amz-meta-tag" value="" /><br />
    <input type="hidden" name="Policy" value='<Base64-encoded policy string>' />
    <input type="hidden" name="X-Amz-Signature" value="<signature-value>" />
    File: 
    <input type="file"   name="file" /> <br />
    <!-- The elements after this will be ignored -->
    <input type="submit" name="submit" value="Upload to Amazon S3" />
  </form>

</html>

这里是我获取表格并查找更多示例的链接(点击此处)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接