【问题标题】:Upload directly to S3 from django从 django 直接上传到 S3
【发布时间】:2012-03-14 08:53:36
【问题描述】:

我真的被困在这里了。

我希望能够从 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 是否具有我正在寻找的功能。

【问题讨论】:

  • 你在那个位置有脚本吗?在尝试执行之前它不会给出错误。如果你有这样的脚本,你能发布更多的代码吗?
  • 刚刚遇到了这个确切的问题——你有没有想过这个问题?
  • 和我一样,使用与他相同的 django-storages 应用程序。他链接到的说明显示了设置,然后指示使用 django shell 来查看更改的效果。但是,没有任何变化,django 会报告常规的默认文件存储。如果我解决了,我会在这里更新。
  • 这个答案对我有帮助:stackoverflow.com/questions/5108186/…

标签: python django django-forms amazon-s3


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这并不难。这些步骤是生成一个策略文档,对其进行签名,然后使用该签名将文件 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> 
    

    【讨论】:

      【解决方案3】:

      为了直接上传到 S3(绕过您的网络服务器),您需要通过浏览器直接发布到预先授权的 url。阅读来自亚马逊的this article,了解它的工作原理。

      我不知道在 django 中有什么可以为你做这件事,但你自己提出请求并不太难。您也可以使用 uploadify 之类的东西从浏览器中进行实际发布,您只需为其提供正确的 url。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-05
        • 2018-12-15
        • 1970-01-01
        • 2020-11-14
        • 2018-08-24
        • 1970-01-01
        • 2011-09-01
        • 2015-04-12
        相关资源
        最近更新 更多