从django直接上传到S3

时间:2012-02-23 21:36:37

标签: python django django-forms amazon-s3

我真的被困在这里。

我希望能够从django表单直接上传到S3。 这将用于保存显示图片。

我遵循了这个:http://django-storages.readthedocs.org/en/latest/backends/amazon-S3.html

但遗憾的是我不得不加入

DEFAULT_FILE_STORAGE = 'storages.backends.s3.S3Storage'
由于某种原因

到settings.py. django甚至不承认我所做的改变。 (我将其更改为DEFAULT_FILE_STORAGE ='asdsfsdfsdf',它甚至没有出错。 有趣的是,我甚至不知道django-storages是否具有我正在寻找的功能。

3 个答案:

答案 0 :(得分:4)

Here's我曾写过的一个工作示例,django-s3upload

答案 1 :(得分:3)

这并不太难。步骤是生成策略文档,对其进行签名,然后使用该签名将文件POST到S3。我写了一个名为sbit3的小应用程序。看看这里:https://github.com/victortrac/sbit3/blob/master/server/sbit3.py,特别是PostHandler类:

class PostHandler(tornado.web.RequestHandler):
    def _generate_policy_doc(self, conditions, expiration=None):
        if not expiration:
            # Sets a policy of 15 minutes to upload file
            expiration = datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
        conditions = [ { "bucket" : conditions["bucket"] },
                       [ "starts-with", "$key", "uploads/"],
                       { "acl" : conditions["acl"] },
                       { "success_action_redirect" : conditions["success_action_redirect"] } ]
        conditions_json = json.dumps({ "expiration" : expiration.strftime("%Y-%m-%dT%H:%M:%SZ"),
                                       "conditions" : conditions })
        logging.debug("Policy doc generated: {0}".format(conditions_json))
        return base64.b64encode(conditions_json)

    def _sign_policy(self, policy):
        signature = base64.b64encode(hmac.new(settings.aws_secret_key, policy, hashlib.sha1).digest())
        return signature

    def get(self, expiration):
        try:
            expiration = int(expiration)
            # Set max expiration to 7200 minutes (5 days)
            if not 0 < expiration < 7200:
                raise tornado.web.HTTPError(403)
            _expireTimestamp = datetime.datetime.utcnow() + datetime.timedelta(minutes=expiration)
        except ValueError:
            raise tornado.web.HTTPError(403)

        # Associate _uuid to expiration in sdb

        _uuid = uuid.uuid4().hex
        sdb_conn.add_item(_uuid, expireTimestamp=_expireTimestamp)

        conditions = { "bucket" : settings.bucket,
                       "acl" : settings.acl,
                       "success_action_redirect" : settings.site_url + "/f/" + _uuid }
        policy_document = self._generate_policy_doc(conditions)
        signature = self._sign_policy(policy_document)

        self.render("post.html", conditions=conditions,
                                 aws_access_id=settings.aws_access_id,
                                 policy_document=policy_document,
                                 signature=signature)

查看设置表单的post.html

<form action="https://{{ conditions["bucket"] }}.s3.amazonaws.com" method="post" enctype="multipart/form-data">
  <input type="hidden" name="key" value="uploads/${filename}">
  <input type="hidden" name="AWSAccessKeyId" value="{{ aws_access_id }}"> 
  <input type="hidden" name="acl" value="{{ conditions["acl"] }}"> 
  <input type="hidden" name="success_action_redirect" value="{{ conditions["success_action_redirect"] }}">
  <input type="hidden" name="policy" value="{{ policy_document }}">
  <input type="hidden" name="signature" value="{{ signature }}">

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

答案 2 :(得分:2)

要直接上传到S3(绕过您的网络服务器),您需要直接通过浏览器发布到预先授权的网址。阅读亚马逊的this article,了解它需要如何运作。

我不知道任何能在django中为你做这件事的事情,但要自己提出这个要求并不太难。您还可以使用uploadify之类的内容从浏览器进行实际发布,您只需要为其提供正确的网址。