我正在尝试找出一种方法将文件发送到 S3 到具有任意“目录”和“文件名”的签名 URL。了解 S3 没有目录。
我可以使用以下命令成功生成签名网址并上传任意文件名:
Lambda 创建签名 URL:
def lambda_handler(event, context):
def create_presigned_post(bucket_name, object_name="${filename}",
fields=None, conditions=None, expiration=3600):
"""Generate a presigned URL S3 POST request to upload a file
:param bucket_name: string
:param object_name: string
:param fields: Dictionary of prefilled form fields
:param conditions: List of conditions to include in the policy
:param expiration: Time in seconds for the presigned URL to remain valid
:return: Dictionary with the following keys:
url: URL to post to
fields: Dictionary of form fields and values to submit with the POST
:return: None if error.
"""
# Generate a presigned S3 POST URL
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_post(bucket_name,
object_name,
Fields=fields,
Conditions=conditions,
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL and required fields
return response
bucketName = "myBucket"
s3client = boto3.client("s3")
signed_url = create_presigned_post(bucketName)
return signed_url
请求上传文件:
session = boto3.Session(profile_name='dev')
object_name = 'test2.txt'
bucket = 'myBucket'
response = {
"url": "https://mys3url.com",
"fields": {
"key": "${filename}",
"AWSAccessKeyId": "...",
"x-amz-security-token": "...",
"policy": "...",
"signature": "..."
}
}
if response is None:
exit(1)
# Demonstrate how another Python program can use the pre-signed URL to upload a file
with open(object_name, 'rb') as f:
s3_object_name = f"this/is/a/test/dir/{object_name}"
files = {'file': (s3_object_name, f)}
http_response = requests.post(response['url'], data=response['fields'], files=files)
# If successful, returns HTTP status code 204
print(f'File upload HTTP status code: {http_response.status_code}')
print(f'{http_response.content}')
当文件 test2.txt 写入存储桶“root”时,这基本上可以正常工作。
但是我想将其上传到
this/is/a/test/dir/
或S3存储桶中的任何其他目录。
我确实理解预签名 url 本质上是限制性的,并且这种限制可能是设计使然,但是如果 s3 没有目录结构,只需命名文件即可将其写入“目录”?
使用
${filename}
允许我将任何文件名写入 S3,但似乎会从文件名中删除任何目录结构。
有用的链接帮助我走到这一步。
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html
但是我想将其上传到
或S3存储桶中的任何其他目录。this/is/a/test/dir/
来自文档:
– 键名,可以选择在末尾添加Key (string)
以附加提交的文件名。请注意,关键相关条件和字段已为您填写,不应包含在“字段”或“条件”参数中。${filename}
像这样使用它:
s3_client.generate_presigned_post(bucket_name, "this/is/a/test/dir/{$filename}")
这将生成一个带有签名 POST 策略的 URL,该策略将接受多部分表单数据并从其文件部分的
$filename
填充 Content-Disposition: filename
部分。