使用Python/Boto/Django直接上传到S3以构造策略

使用Python/Boto/Django直接上传到S3以构造策略,python,django,amazon-s3,amazon-web-services,plupload,Python,Django,Amazon S3,Amazon Web Services,Plupload,到目前为止,我已经对这个问题进行了多次迭代,搜索了许多不同的示例,并且已经阅读了所有文档 我正在尝试将Plupload()与awss3directpost方法()结合起来。然而,我相信我构建传输策略和签名的方式有问题。当我提交表单时,我没有收到服务器的响应,而是重置了与服务器的连接 我尝试在示例中使用python代码: import base64 import hmac, sha policy = base64.b64encode(policy_document) signature = b

到目前为止,我已经对这个问题进行了多次迭代,搜索了许多不同的示例,并且已经阅读了所有文档

我正在尝试将Plupload()与awss3directpost方法()结合起来。然而,我相信我构建传输策略和签名的方式有问题。当我提交表单时,我没有收到服务器的响应,而是重置了与服务器的连接

我尝试在示例中使用python代码:

import base64
import hmac, sha

policy = base64.b64encode(policy_document)

signature = base64.b64encode(
hmac.new(aws_secret_key, policy, sha).digest())
我还尝试使用python中更新的hashlib库。无论我使用何种方法构建策略和签名,我总是得到不同于此处生成的值:

我已看完这个问题:

但我发现提供的示例过于复杂,无法准确地实现它们

我最近的尝试是使用boto库的部分内容:

但是使用S3Commection.build\u post\u form\u args方法对我也不起作用

如果有人能提供一个关于如何使用python创建post表单的适当示例,我将非常感谢。即使是一些关于为什么总是重置连接的简单见解也不错

一些警告:

如果可能的话,我想使用hashlib。 我想从Amazon获得一个XML响应(大概是“success\u action\u status='201'”这样做的) 我需要能够上传较大类型的文件,最大大小约2GB


最后一点注意,当我在Chrome中运行此程序时,它提供了上载进度,而上载通常会失败37%左右。

我尝试使用Boto,但发现它不允许我放入所有我想要的标题。下面您可以看到我如何生成策略、签名和post表单值字典

请注意,所有x-amz-meta-*标记都是自定义标题属性,您不需要它们。还请注意,表单中的几乎所有内容都需要在策略中进行编码和签名

def generate_post_form(bucket_name, key, post_key, file_id, file_name, content_type):
  import hmac
  from hashlib import sha1
  from django.conf import settings
  policy = """{"expiration": "%(expires)s","conditions": [{"bucket":"%(bucket)s"},["eq","$key","%(key)s"],{"acl":"private"},{"x-amz-meta-content_type":"%(content_type)s"},{"x-amz-meta-file_name":"%(file_name)s"},{"x-amz-meta-post_key":"%(post_key)s"},{"x-amz-meta-file_id":"%(file_id)s"},{"success_action_status":"200"}]}"""
  policy = policy%{
    "expires":(datetime.utcnow()+settings.TIMEOUT).strftime("%Y-%m-%dT%H:%M:%SZ"), # This has to be formatted this way
    "bucket": bucket_name, # the name of your bucket
    "key": key, # this is the S3 key where the posted file will be stored
    "post_key": post_key, # custom properties begin here
    "file_id":file_id,
    "file_name": file_name,
    "content_type": content_type,
  }
  encoded = policy.encode('utf-8').encode('base64').replace("\n","") # Here we base64 encode a UTF-8 version of our policy.  Make sure there are no new lines, Amazon doesn't like them.
  return ("%s://%s.s3.amazonaws.com/"%(settings.HTTP_CONNECTION_TYPE, self.bucket_name),
          {"policy":encoded,
           "signature":hmac.new(settings.AWS_SECRET_KEY,encoded,sha1).digest().encode("base64").replace("\n",""), # Generate the policy signature using our Amazon Secret Key
           "key": key,
           "AWSAccessKeyId": settings.AWS_ACCESS_KEY, # Obviously the Amazon Access Key
           "acl":"private",
           "x-amz-meta-post_key":post_key,
           "x-amz-meta-file_id":file_id,
           "x-amz-meta-file_name": file_name,
           "x-amz-meta-content_type": content_type,
           "success_action_status":"200",
          })
然后,可以使用返回的元组生成一个表单,将字典中的所有键值对作为隐藏字段和实际文件输入字段(其名称/id应为“file”)发布到生成的S3URL

希望这有助于作为一个例子。

尝试签出
它将PLUPLOAD与直接S3上传相结合

我已经为同样的问题苦苦挣扎了好几天,使用了几乎相同的代码。(请参阅)刚刚尝试根据White Box Dev的代码对我的策略进行编码,但仍然没有像AWS建议的那样进行编码。我最终放弃了,用

…并将返回的值插入HTML表单中。效果很好


@Oodles先生:如果您将aws_secret_密钥存储在一个单独的文件中,请在生成签名之前使用bash命令ls-al检查它的字节数。它应该有40字节长。正如White Box Dev所指出的,AWS不喜欢\n,并且在保存时可能将此隐藏字符(或回车符或^M)与AWS_secret_密钥字符串捆绑在一起……因此使其长度为41字节。您可以尝试.replace(“\n”、”)或.rstrip()将其读入脚本后删除。encode(“utf-8”)也可能适用于您。然而,这些都不适合我。好奇你是在Windows还是Unix上运行Python。。。您还可以尝试使用emacs保存字符串,而无需编辑器自动插入。\n。我已经包括了两个目前对我有效的解决方案

第一个解决方案使用普通Python。第二个使用boto

我试着先让boto工作,但总是出错。所以我回到AmazonRuby文档,让S3在不使用boto的情况下使用python接受文件。()

在了解发生了什么之后,我能够修复错误并使用boto,这是一个更简单的解决方案

我之所以包括解决方案1,是因为它明确显示了如何使用python设置策略文档和签名

我的目标是将html上传页面创建为动态页面,以及用户在成功上传后看到的“成功”页面。解决方案1显示表单上传页面的动态创建,而解决方案2显示上传表单页面和成功页面的创建

解决方案1:

导入base64
导入hmac、hashlib
######仅编辑以下项目######
调试=1
AWS_SECRET_KEY=“MySecretKey”
AWS\u ACCESS\u KEY=“MyAccessKey”
HTML\u NAME=“S3PostForm.HTML”
过期日期=“2015-01-01T00:00:00Z”#2015年1月1日格林尼治标准时间
文件到上传=“${filename}”
BUCKET=“media.mysite.com”
KEY=“”
ACL=“公共阅读”或“私人”
成功=”http://media.mysite.com/success.html"
CONTENT_TYPE=“”
内容长度=1024**3千兆字节
HTTP_或_HTTPS=“HTTP”#或“HTTPS”以提高安全性
PAGE_TITLE=“我的Html上传到S3表单”
ACTION=“%s://%s.s3.amazonaws.com/”%(HTTP\u或HTTPS,BUCKET)
######不要从这里往下编辑######
策略\文档\数据={
“到期”:到期日,
“bucket_name”:bucket,
“密钥名称”:密钥,
“acl_名称”:acl,
“成功”:成功,
“内容名称”:内容类型,
“内容长度”:内容长度,
}
政策文件“”
{“到期”:“%(到期)s”,
“条件”:[
{“bucket”:“%(bucket_name)s”},
[“以”、“$key”、“%(key_name)s”开头],
{“acl”:“%(acl_名称)s”},
{“success_action_redirect”:“%(success_redirect)s”},
[“以”、“$Content Type”、“%(Content_name)s”开头],
[“内容长度范围”,0,%(内容长度)d]
]
}
“%policy\u文档\u数据”
policy=base64.b64编码(policy\u文档)
signature=base64.b64encode(hmac.new(AWS\u SECRET\u KEY,policy,hashlib.sha1.digest())
html\u页面\u数据={
“页面标题”:页面标题,
“行动名称”:行动,
“文件名”:文件上传到,
“访问名称”:AWS访问密钥,
“acl_名称”:acl,