python-3.x - 如何使用 boto3 和 lambda 从 S3 存储桶中的 html 页面上传文件?
问题描述
我想将大于 10 MB 的文件从 html 页面上传到 S3。
我有html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Upload File to S3 Bucket</title>
</head>
<body>
<h3>Upload File to S3 Bucket</h3>
<form
action=" https://4oss3kkck9.execute-api.us-east-1.amazonaws.com/api/uploadhtml"
method="post"
enctype="multipart/form-data"
>
<h1>Select File:</h1>
<input type="file" name="file" />
<input type="submit" name="submit" value="Upload" />
</form>
</body>
</html>
我有一个由 API 端点触发的 lambda 函数:
这是 Lambda:
import json
import base64
import boto3
import email
import logging
import botocore
from create_bucket import create_bucket
def lambda_handler(event, context):
s3 = boto3.client('s3')
buckets = s3.list_buckets()
bucket_name = ""
bucket_without_extension = "filetypewithoutextension"
print("Received event: " + json.dumps(event))
# decoding form-data into bytes
post_data = base64.b64decode(event["body"])
# fetching content-type
try:
content_type = event["headers"]["content-Type"]
except:
content_type = event["headers"]["content-type"]
# concate Content-Type: with content_type from event
ct = "Content-Type: "+content_type+"\n"
# parsing message from bytes
msg = email.message_from_bytes(ct.encode()+post_data)
print(msg)
# checking if the message is multipart
print("Multipart check : ", msg.is_multipart())
# if message is multipart
if msg.is_multipart():
multipart_content = {}
# retrieving form-data
for part in msg.get_payload():
# checking if filename exist as a part of content-disposition header
if part.get_filename():
# fetching the filename
file_name = part.get_filename()
bucket_name = f"thisismycomplicatedbucketfiletype-{file_name.split('.')[-1]}"
multipart_content[part.get_param("name", header="content-disposition")] = part.get_payload(decode=True)
in_bucket = False
if len(file_name.split(".")) == 1 or file_name.split(".")[1] == "":
s3.put_object(Bucket=bucket_without_extension, Key=file_name, Body=multipart_content["file"],
ServerSideEncryption="aws:kms")
return {
"statusCode": 200,
"body": json.dumps("File uploaded successfully!")
}
for bucket in buckets["Buckets"]:
if bucket_name in bucket["Name"]:
s3.put_object(Bucket=bucket_name, Key=file_name, Body=multipart_content["file"],
ServerSideEncryption="aws:kms")
in_bucket = True
break
if not in_bucket:
create_bucket(bucket_name)
s3.put_object(Bucket=bucket_name, Key=file_name, Body=multipart_content["file"],
ServerSideEncryption="aws:kms")
# on upload success
return {
"statusCode": 200,
"body": json.dumps("File uploaded successfully!")
}
else:
# on upload failure
return {
"statusCode": 500,
"body": json.dumps("Upload failed!")
}
但这仅适用于最大 10 MB 的文件。我想上传所有文件扩展名,还有小文件和大于 10 MB 的文件?
如何修改这段代码?预设网址?分段上传?
我不确定如何实现这一点?
谢谢!
解决方案
文件大于 10 MB?
遗憾的是,您无法通过 API 网关执行此操作。它的硬限制是10 MB。常见的解决方法是使用S3 预签名 url将文件上传到 S3。这需要更改您的架构,因为要上传到 S3,您不能使用 API 网关。
推荐阅读
- python - mpg123 不能在 ide 中工作,但可以在 cmd 中工作
- mysql - 无法使用 pip 安装 mysqlclient
- xml - XSLT 在特定标签 w/attribute 存在时选择?
- python - 如何重新组织 python 模块以不反映目录结构?
- javascript - 我正在尝试使用 fetch API 和 formData 上传文件 - 角度材料
- python - 如何使用 tkinter 中的按钮更改标签和背景的颜色
- c++ - 这个 typedef 和转换运算符语法是什么意思?
- json - Jenkins 错误 net.sf.json.JSONException:无效的 JSON 字符串
- arrays - 如何在 NASM 中实现二维数组
- arrays - declare var as a group in swift