我试着写一个python lambda函数,返回一个预先签名的url来放置一个对象。
import os
import boto3
import json
import boto3
session = boto3.Session(region_name=os.environ['AWS_REGION'])
s3 = session.client('s3', region_name=os.environ['AWS_REGION'])
upload_bucket = 'BUCKER_NAME' # Replace this value with your bucket name!
URL_EXPIRATION_SECONDS = 30000 # Specify how long the pre-signed URL will be valid for
# Main Lambda entry point
def lambda_handler(event, context):
return get_upload_url(event)
def get_upload_url(event):
key = 'testimage.jpg' # Random filename we will use when uploading files
# Get signed URL from S3
s3_params = {
'Bucket': upload_bucket,
'Key': key,
'Expires': URL_EXPIRATION_SECONDS,
'ContentType': 'image/jpeg' # Change this to the media type of the files you want to upload
}
# Get signed URL
upload_url = s3.generate_presigned_url(
'put_object',
Params=s3_params,
ExpiresIn=URL_EXPIRATION_SECONDS
)
return {
'statusCode': 200,
'isBase64Encoded': False,
'headers': {
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(upload_url)
}
代码本身可以工作,并返回一个带签名的URL,格式为“https://BUCKET_NAME.s3.amazonaws.com/testimage. jpg?...”
但是,当使用POSTMAN尝试放置对象时,它加载而不结束。
最初我认为这是因为我的代码,过了一段时间我写了一个NodeJS函数做同样的事情:
const AWS = require('aws-sdk')
AWS.config.update({ region: process.env.AWS_REGION })
const s3 = new AWS.S3()
const uploadBucket = 'BUCKET_NAME' // Replace this value with your bucket name!
const URL_EXPIRATION_SECONDS = 30000 // Specify how long the pre-signed URL will be valid for
// Main Lambda entry point
exports.handler = async (event) => {
return await getUploadURL(event)
}
const getUploadURL = async function(event) {
const randomID = parseInt(Math.random() * 10000000)
const Key = 'testimage.jpg' // Random filename we will use when uploading files
// Get signed URL from S3
const s3Params = {
Bucket: uploadBucket,
Key,
Expires: URL_EXPIRATION_SECONDS,
ContentType: 'image/jpeg' // Change this to the media type of the files you want to upload
}
return new Promise((resolve, reject) => {
// Get signed URL
let uploadURL = s3.getSignedUrl('putObject', s3Params)
resolve({
"statusCode": 200,
"isBase64Encoded": false,
"headers": {
"Access-Control-Allow-Origin": "*"
},
"body": JSON.stringify(uploadURL)
})
})
}
NodeJs版本给了我一个格式为“https://BUCKET_www.example.com“的URLNAME.s3.eu-west-1.amazonaws.com/testimage.jpg?
两者的主要区别是aws子域,当使用NodeJS时,它给出“BUCKET_NAME.s3.eu-west-1.amazonaws.com”,当使用Python时,给出“https://BUCKET_NAME.s3. amazonaws.com”
当使用python时,该区域不出现。我试过,使用python生成的签名url手动添加“s3.eu-west-1”,它工作!!
这是AWS Boto 3 python库中的bug吗?正如您所看到的,在python代码中,我尝试指定区域,但它没有执行任何操作。
有什么想法吗,伙计们?我想解开这个谜团:)
先谢谢你了,
莱奥
1条答案
按热度按时间nkhmeac61#
我能够在us-east-1中重现这个问题。Github中有一些bug(例如,this和this),但建议的解决方案不一致。
解决方法是为bucket创建一个面向Internet的接入点,然后将接入点的完整ARN赋给
upload_bucket
变量。请注意,Lambda将创建一个预签名的URL,但只有在Lambda具有附加到其执行角色的适当权限策略时,它才能工作。