当前位置: 首页 > article >正文

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

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

在这里插入图片描述

问题背景

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

解决方案

解决方案 1:使用纯 Python

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

###### 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 库

from boto.s3 import connection

步骤 2:设置 S3 连接

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

# 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 后端来处理文件上传。


http://www.kler.cn/a/541425.html

相关文章:

  • Mp4视频播放机无法播放视频-批量修改视频分辨率(帧宽、帧高)
  • 【C++八股】 前置 ++i vs. 后置 i++ 的区别
  • 机器学习怎么学习,还有算法基本的源代码
  • Mac(m1)本地部署deepseek-R1模型
  • 2月10日QT
  • 数据集成实例分享:金蝶云星空对接旺店通实现库存管理自动化
  • Django操作指令大集合说明
  • electron中调用C++
  • 视频编解码标准总结
  • 1.15 联邦学习
  • 《Wiki.js知识库部署实践 + CNB Git数据同步方案解析》
  • AI算力的摆脱有点像发动机汽车变电动车
  • 第22章 Balking设计模式(Java高并发编程详解:多线程与系统设计)
  • 牛客周赛Round 80 —— 举手赢棋 python 补题 + 题解
  • 数据结构之八大排序算法
  • Visual Studio 2022 中使用 Google Test
  • k8s:pod被kill,显示command terminated with exit code 137
  • Python Pandas(7):Pandas 数据清洗
  • UDP小实验
  • #渗透测试#批量漏洞挖掘#某成科信票务管理系统 TicketManager SQL注入漏洞
  • MapReduce简单应用(三)——高级WordCount
  • C#操作excel数据,第一步先保存到Redis,第二步再保存到Sql Server数据库。第三步同步到MongoDB中
  • Lisp语言的算法
  • 51单片机独立按键的扩展应用
  • Linux ping不通百度但浏览器可以打开百度的的解决方法
  • 抖音“碰一碰”发视频:短视频社交的新玩法