据我所知,预签名url是一种授予外部人员通过给定url进行操作的权限的方法,但是此url在形式上似乎非常严格。检查签名时的任何差异都可能导致403
对于下载而言,这很简单,但是对于上载呢?
假设我想生成一个将test.txt
上传到testbucket
的网址,我可以使用
s3.generate_presigned_url(ClientMethod='put_object', Params={'Bucket': 'testbucket', 'Key': 'test.txt'}, HttpMethod='PUT', ExpiresIn=120)
但是这样做会导致在调用url(requests.put(url)
)时我的存储桶中有一个空文件
我必须指定
之类的内容with open(some_file, 'rb') as f:
s3.generate_presigned_url(ClientMethod='put_object', Params={'Bucket': 'testbucket', 'Key': 'test.txt', 'Body': f.read()}, HttpMethod='PUT', ExpiresIn=120)
为了真正获得有意义的上载。
但这会否破坏目的?该URL应该发送给其他人使用。如果我已经知道有关文件的所有信息,包括其内容,那是否意味着我已经拥有文件了?如果它是一个未知文件,我只能得到一些信息,例如file_name
,也许还有content-length
和content-type
怎么办?
即使说我创建一个API端点并要求用户传入数据(我想包括其内容),然后生成供用户使用的url,我也可能会得到数据并直接上传,而不是通过预先签名的网址,对吧?
这是一笔交易。我想进行多部分上传时,看起来会变得更加复杂。我需要为该用户生成多个预签名的URL吗?我觉得这没有道理。有人可以教育我吗?
答案 0 :(得分:2)
您不提供尸体。您提供存储桶和密钥,SDK为您提供了一个预签名的URL,并且您与客户端共享了该URL。然后,您的客户端将文件上传到该URL。您指定存储区和对象键,而客户端提供文件内容。
下面是一个如何为上传生成预签名URL的示例:
import boto3
s3 = boto3.client('s3')
print s3.generate_presigned_url('put_object', { 'Bucket': 'xxx', 'Key': 'yyy' }, 3600)
下面是一个如何上传到预先签名的URL的示例:
import requests
payload = 'fred'
url = <whatever previous script returned>
r = requests.put(url, data=payload)
r.raise_for_status()