Browser-Based Upload using HTTP POST

0

This is my HTML POST Form.

<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>

I got this from the AWS S3 Docs shown below.

https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html

From AWS Console I have gotten my security credentials: Access Key = XXXX Secret Ket = XXXX

I am aware that I need to set values for "Policy" and "X-Amz-Signature" but I am not sure as to how to do that.

In the docs they have mentioned that I need to StringToSign and get the Policy/Signature but I am not sure how to do that.

Can someone help me as to how to generate Policy(Base64-encoded policy string) and Signature for my HTML FORM ?

질문됨 2년 전544회 조회
1개 답변
1

Hi,

To base64 encode a string you can use online encoders (for example https://www.base64encode.org). Note: there are also operating system specific command line tools for base64 encoding for example base64 on Linux/MacOS. It is important that you make sure that the input has CRLF line endings. The online encoder lets you select CRLF in the dropdown.

The section Sample Policy and Form in the documentation you posted https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html shows how a policy document should look like. If you need help on how to change the values in the policy document to work with your S3 bucket please let me know. Otherwise you can copy that policy and decode it as I described in the previous paragraph (online decoder is probably the easiest). Now you have the base64 encoded policy.

To sign the base64 encoded policy you could use the following Python script (derived from this documentation https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html). Note: I am using this Python script because it is OS independent. There are also command line tools for hmac-sha256 cryptography. However, describing them for all the OS's is more complicated than just using a Python script.

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

"""
Important

The AWS SDKs sign API requests for you using the access key that you specify when you
configure the SDK. When you use an SDK, you don’t need to learn how to sign API requests.
We recommend that you use the AWS SDKs to send API requests, instead of writing your own code.

The following example is a reference to help you get started if you have a need to write
your own code to send and sign requests. The example is for reference only and is not
maintained as functional code.
"""

# AWS Version 4 signing example

# EC2 API (DescribeRegions)

# See: http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
# This version makes a GET request and passes the signature
# in the Authorization header.
import sys, os, base64, datetime, hashlib, hmac 

service = 's3'
date = '20151229'
region = 'us-east-1'
string_to_sign = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9"

key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

kDate = sign(('AWS4' + key).encode('utf-8'), date)
kRegion = sign(kDate, region)
kService = sign(kRegion, service)
kSigning = sign(kService, 'aws4_request')
signature = hmac.new(kSigning, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
print(signature)

If you modify the policy from the one in the documentation then you need to replace the string_to_sign with your new base64 encoded policy. If you use your own S3 bucket you will also have to update the date and region accordingly and replace the key with your access key.

The output of the python scrip is the signature.

If you have any questions on how to adapt the example from the documentation to using your own S3 bucket don't hesitate to ask.

May I ask why you are not using the AWS SDK for JavaScript?

AWS
답변함 2년 전
  • Uploading is working , i am trying to upload a .glb model to s3 but it's not working <input type="hidden" name="Content-Type" value="image/png"> because of this tag it's giving .png extension to every file which i download from s3, is there any way i can upload .glb file type using input tag ?

  • According to Wikipedia (https://en.wikipedia.org/wiki/GlTF) the internet media type for .glb files is model/gltf-binary. So you need to update your html and policy with the media type. Change <input type="input" name="Content-Type" value="image/png" /><br /> to <input type="input" name="Content-Type" value="model/gltf-binary" /><br />

    and in the policy document change ["starts-with", "$Content-Type", "image/"] to ["starts-with", "$Content-Type", "model/gltf-binary"]

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠