在golang中创建POST策略并将其签名为基于浏览器的上传到Amazon S3

时间:2018-01-15 11:49:34

标签: go amazon-s3 file-upload

我正在尝试从我的客户端(AngularJS)实现基于浏览器的上传到amazon S3,经过一些研究后我才知道我必须创建一个策略并签署S3的POST请求。 通过引用http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html,我尝试了http://play.golang.org/p/3zn5fSDasK

package main
  import "fmt"
  import "encoding/base64"

  func main() {
     bytePolicy := []byte(`{ 
                "expiration": "2013-08-06T12:00:00.000Z",
                "conditions": [
                         {"bucket": "examplebucket"},
                         ["starts-with", "$key", "user/user1/"],
                         {"acl": "public-read"},
                         {"success_action_redirect": "http://acl6.s3.amazonaws.com/successful_upload.html"},
                         ["starts-with", "$Content-Type", "image/"],
                         {"x-amz-meta-uuid": "14365123651274"},
                         ["starts-with", "$x-amz-meta-tag", ""],
                         {"x-amz-credential":"AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request"},
                         {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
                         {"x-amz-date": "20130806T000000Z" }
                  ]
              }`)
        fmt.Println(base64.StdEncoding.EncodeToString(bytePolicy))
 }

我也得到了base64加密值。 由于bytepolicy是一种字节,并且接受字符串作为值,因此策略是硬编码的。如何像Javascript的模板文字一样动态更改值? (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)或者我可以通过其他方式创建签名政策吗?

1 个答案:

答案 0 :(得分:0)

您至少有两个选择:使用fmt.Sprintf生成字符串,或使用模板。

使用fmt.Sprintf格式化自己的字符串可能是最快的:playground

// The variables to set the contents to.
key := "mykey"
contentType := "text/plain"

// The "template". Use the proper % modifiers based on your variable types.
templateString := `{ 
                    "expiration": "2013-08-06T12:00:00.000Z",
                    "conditions": [
                            {"bucket": "examplebucket"},
                            ["starts-with", "%s", "user/user1/"],
                            {"acl": "public-read"},
                            {"success_action_redirect": "http://acl6.s3.amazonaws.com/successful_upload.html"},
                            ["starts-with", "%s", "image/"],
                            // etc...
                      ]
                }`

// Format the string.
filledTemplate := fmt.Sprintf(templateString, key, contentType)
fmt.Println(filledTemplate)

// Make a byte slice.
bytePolicy := []byte(filledTemplate)
fmt.Println(base64.StdEncoding.EncodeToString(bytePolicy))

另一种可能更简洁的方法是使用text/templateplayground

templateString := `{ 
                    "expiration": "2013-08-06T12:00:00.000Z",
                    "conditions": [
                            {"bucket": "examplebucket"},
                            ["starts-with", "{{- .Key -}}", "user/user1/"],
                            {"acl": "public-read"},
                            {"success_action_redirect": "http://acl6.s3.amazonaws.com/successful_upload.html"},
                            ["starts-with", "{{- .ContentType -}}", "image/"],
                            // Etc...
                      ]
                }`

type TemplateInfo struct {
    Key, ContentType string
}

myInfo := TemplateInfo{
    Key:         "mykey",
    ContentType: "text/plain",
}

t := template.Must(template.New("awsfields").Parse(templateString))

var out bytes.Buffer
if err := t.Execute(&out, myInfo); err != nil {
    panic(err)
}
fmt.Println(out.String())
fmt.Println(base64.StdEncoding.EncodeToString(out.Bytes()))