前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >使用 Python/Boto/Django 实现 S3 直接上传

使用 Python/Boto/Django 实现 S3 直接上传

原创
作者头像
华科云商小徐
发布2025-02-07 13:06:39
发布2025-02-07 13:06:39
8300
代码可运行
举报
运行总次数:0
代码可运行

要使用 Python 和 Boto3(AWS SDK for Python)直接从 Django 上传文件到 S3,你需要配置 AWS 的 S3 存储桶,并在 Django 项目中设置 boto3 来与 S3 进行交互。

问题背景

在使用 Plupload 和 AWS S3 直接上传时,试图使用 Python/Boto/Django 进行构建策略并上传文件,但一直收到错误消息或连接重置,无法成功上传。

解决方案

解决方案 1:使用纯 Python

步骤 1:设置策略文档和签名

代码语言:javascript
代码运行次数:0
复制
###### EDIT ONLY THE FOLLOWING ITEMS ######
​
DEBUG = 1
AWS_SECRET_KEY = "MySecretKey"
AWS_ACCESS_KEY = "MyAccessKey"
HTML_NAME = "S3PostForm.html"
EXPIRE_DATE = "2015-01-01T00:00:00Z" # Jan 1, 2015 gmt
FILE_TO_UPLOAD = "${filename}"
BUCKET = "media.mysite.com"
KEY = ""
ACL = "public-read" # or "private"
SUCCESS = "http://media.mysite.com/success.html"
CONTENT_TYPE = ""
CONTENT_LENGTH = 1024**3 # One gigabyte
HTTP_OR_HTTPS = "http" # Or "https" for better security
PAGE_TITLE = "My Html Upload to S3 Form"
ACTION = "%s://%s.s3.amazonaws.com/" % (HTTP_OR_HTTPS, BUCKET)
​
###### DON'T EDIT FROM HERE ON DOWN ######
​
policy_document_data = {
"expire": EXPIRE_DATE,
"bucket_name": BUCKET,
"key_name": KEY,
"acl_name": ACL,
"success_redirect": SUCCESS,
"content_name": CONTENT_TYPE,
"content_length": CONTENT_LENGTH,
}
​
policy_document = """
{"expiration": "%(expire)s",
  "conditions": [ 
    {"bucket": "%(bucket_name)s"}, 
    ["starts-with", "$key", "%(key_name)s"],
    {"acl": "%(acl_name)s"},
    {"success_action_redirect": "%(success_redirect)s"},
    ["starts-with", "$Content-Type", "%(content_name)s"],
    ["content-length-range", 0, %(content_length)d]
  ]
}
""" % policy_document_data
​
policy = base64.b64encode(policy_document)
signature = base64.b64encode(hmac.new(AWS_SECRET_KEY, policy, hashlib.sha1).digest())
​
html_page_data = {
"page_title": PAGE_TITLE,
"action_name": ACTION,
"filename": FILE_TO_UPLOAD,
"access_name": AWS_ACCESS_KEY,
"acl_name": ACL,
"redirect_name": SUCCESS,
"policy_name": policy,
"sig_name": signature,
"content_name": CONTENT_TYPE,
}
​
html_page = """
<html> 
 <head>
  <title>%(page_title)s</title> 
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 </head>
<body>
 <form action="%(action_name)s" method="post" enctype="multipart/form-data">
  <input type="hidden" name="key" value="%(filename)s">
  <input type="hidden" name="AWSAccessKeyId" value="%(access_name)s">
  <input type="hidden" name="acl" value="%(acl_name)s">
  <input type="hidden" name="success_action_redirect" value="%(redirect_name)s">
  <input type="hidden" name="policy" value="%(policy_name)s">
  <input type="hidden" name="signature" value="%(sig_name)s">
  <input type="hidden" name="Content-Type" value="%(content_name)s">
​
  <!-- Include any additional input fields here -->
​
  Browse to locate the file to upload:<br \> <br \>
​
  <input name="file" type="file"><br> <br \>
  <input type="submit" value="Upload File to S3"> 
 </form> 
</body>
</html>
""" % html_page_data
​
with open(HTML_NAME, "wb") as f:
    f.write(html_page)
​
###### Dump output if testing ######
if DEBUG:
​
    if 1: # Set true if not using the LEO editor
        class G:
            def es(self, data):print(data)
        g = G()
​
    items = [
    "",
    "",
    "policy_document: %s" % policy_document,
    "ploicy: %s" % policy,
    "signature: %s" % signature,
    "",
    "",
    ]
    for item in items:
        g.es(item)

步骤 2:创建 HTML 上传表单

使用 html_page_data 字典中的值动态创建 HTML 上传表单。

步骤 3:保存上传表单

将 html_page 变量的内容保存到 HTML 文件中。

解决方案 2:使用 boto

步骤 1:导入 boto 库

代码语言:javascript
代码运行次数:0
复制
from boto.s3 import connection

步骤 2:设置 S3 连接

代码语言:javascript
代码运行次数:0
复制
conn = connection.S3Connection(AWS_ACCESS_KEY,AWS_SECRET_KEY)

步骤 3:构建表单参数

使用 conn.build_post_form_args 方法构建表单参数。

步骤 4:创建 HTML 上传表单

使用 form_fields 变量中的值动态创建 HTML 上传表单。

步骤 5:保存上传表单

将 html_page 变量的内容保存到 HTML 文件中。

步骤 6:创建成功页面

创建一个 HTML 页面来显示上传成功的消息。

步骤 7:保存成功页面

将 success_page 变量的内容保存到 HTML 文件中。

代码例子

解决方案 1:使用纯 Python

代码语言:javascript
代码运行次数:0
复制
# Import required libraries
import base64
import hmac, hashlib
​
# Set up policy document data
policy_document_data = {
    "expire": EXPIRE_DATE,
    "bucket_name": BUCKET,
    "key_name": KEY,
    "acl_name": ACL,
    "success_redirect": SUCCESS,
    "content_name": CONTENT_TYPE,
    "content_length": CONTENT_LENGTH,
}
​
# Construct the policy document
policy_document = """
    {"expiration": "%(expire)s",
      "conditions": [
        {"bucket": "%(bucket_name)s"},
        ["starts-with", "$key", "%(key_name)s"],
        {"acl": "%(acl_name)s"},
        {"success_action_redirect": "%(success_redirect)s"},
        ["starts-with", "$Content-Type", "%(content_name)s"],
        ["content-length-range", 0, %(content_length)d]
      ]
    }
    """ % policy_document_data
​
# Encode the policy document using base64
policy = base64.b64encode(policy_document)
​
# Construct the signature using HMAC-SHA1
signature = base64.b64encode(hmac.new(AWS_SECRET_KEY, policy, hashlib.sha1).digest())
​
# Set up HTML page data
html_page_data = {
    "page_title": PAGE_TITLE,
    "action_name": ACTION,
    "filename": FILE_TO_UPLOAD,
    "access_name": AWS_ACCESS_KEY,
    "acl_name": ACL,
    "redirect_name": SUCCESS,
    "policy_name": policy,
    "sig_name": signature,
    "content_name": CONTENT_TYPE,
}
​
# Construct the HTML page
html_page = """
    <html>
        <head>
            <title>%(page_title)s</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        </head>
        <body>
            <form action="%(action_name)s" method="post" enctype="multipart/form-data">
                <input type="hidden" name="key" value="%(filename)s">
                <input type="hidden" name="AWSAccessKeyId" value="%(access_name)s">
                <input type="hidden" name="acl" value="%(acl_name)s">
                <input type="hidden" name="success_action_redirect" value="%(redirect_name)s">
                <input type="hidden" name="policy" value="%(policy_name)s">
                <input type="hidden" name="signature" value="%(sig

如果你希望直接从前端通过 JavaScript 将文件上传到 S3,可以进一步实现签名请求(presigned URL),但上述方法主要通过 Django 后端来处理文件上传。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档