python-3.x - AWS S3 使用查询参数对请求进行身份验证以下载具有自定义名称的文件
问题描述
我正在尝试创建一个可以让用户从 S3 存储桶下载文件的文件的签名 URL。我正在遵循用docs编写的这种方式。生成的签名运行良好,并且在用户访问 URL 时也可以下载文件。问题是我希望下载文件的名称是自定义的。例如:文件密钥:tg6AbybBgFMidmKy5dz4vVXZ
文件名:test.xlsx
该文件使用密钥保存在 S3 上,没有文件扩展名。
因此,当用户下载文件时,它是无扩展名的,因此操作系统无法识别。我希望它与FileName
. 我尝试添加response-content-disposition
查询,但它引发了错误:
下面是我现在正在使用的代码。
# Create a date for headers and the credential string
time = datetime.datetime.utcnow()
amz_date = time.strftime('%Y%m%dT%H%M%SZ')
datestamp = time.strftime('%Y%m%d') # Date w/o time, used in credential scope
# **CREATE A CANONICAL REQUEST**
canonical_uri = '/' + document_key
canonical_headers = 'host:' + bucket_url + '\n'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
# Create the canonical query string in URL-encoded (space=%20).
canonical_querystring = 'response-content-disposition=attachment; filename="' + document_name + '"; filename*=UTF-8\'\'' + document_name
canonical_querystring += '&response-content-type=' + document_type
canonical_querystring += '&X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + quote_plus(access_key + '/' + credential_scope, safe='')
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=' + url_expiry
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
canonical_request = request_method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers.lower() + '\n' + signed_headers.lower()
# CREATE THE STRING TO SIGN
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# CALCULATE THE SIGNATURE
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
# ADD SIGNING INFORMATION TO THE REQUEST
canonical_querystring += '&X-Amz-Signature=' + signature
# Merge for downloadable URL
download_url = 'https://' + bucket_url + canonical_uri +'?' + canonical_querystring
我没有使用 AWS 开发工具包。我正在尝试自己做!
编辑:即使添加&
了丢失的内容,我也得到了签名不匹配。
解决方案
问题在于编码,我错过&
了canonical_querystring = 'X-Amz-Algorithm
!它杀死了我环顾所有论坛并尝试不同事物的 3 天!这是工作代码!
# Create a date for headers and the credential string
time = datetime.datetime.utcnow()
amz_date = time.strftime('%Y%m%dT%H%M%SZ')
datestamp = time.strftime('%Y%m%d') # Date w/o time, used in credential scope
# **CREATE A CANONICAL REQUEST**
canonical_uri = '/' + document_key
canonical_headers = 'host:' + bucket_url + '\n'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
# Create the canonical query string in URL-encoded (space=%20).
canonical_querystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + quote_plus(access_key + '/' + credential_scope, safe='')
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=' + url_expiry
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
canonical_querystring += '&response-content-disposition=' + quote('attachment; filename=\"' + document_name + '\"; filename*=UTF-8\'\'' + document_name, safe='')
canonical_querystring += '&response-content-type=' + quote(document_type, safe='')
canonical_request = request_method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers.lower() + '\n' + signed_headers.lower() + '\n' + 'UNSIGNED-PAYLOAD'
# CREATE THE STRING TO SIGN
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# CALCULATE THE SIGNATURE
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
# ADD SIGNING INFORMATION TO THE REQUEST
canonical_querystring += '&X-Amz-Signature=' + signature
# Merge for downloadable URL
download_url = 'https://' + bucket_url + canonical_uri +'?' + canonical_querystring
我正在使用
quote_plus('attachment; filename=\"' + document_name + '\"; filename*=UTF-8\'\'' + document_name,)
而不是我不得不使用
quote('attachment; filename=\"' + document_name + '\"; filename*=UTF-8\'\'' + document_name, safe='')
使用此方法/逻辑,您可以生成具有自定义文件名的 S3 对象链接,而无需使用 aws-sdk
推荐阅读
- ios - 无法在 xamarin Visual Studio 中构建 ios 应用程序
- node.js - 无法使用 phantomjs 和 nightwatch.js 从 org.openqa.selenium.remote.NewSessionPayload 创建会话
- javascript - 如何限制框阴影传播不超过父宽度和高度
- dart - Flutter 将文本字段与底部对齐并从顶部对齐文本
- python - Django 错误的 request.POST 属性值已保存
- apache-karaf - Opendaylight - 无法加入集群
- sql - sas proc sql escape '(撇号)
- java - 如何更改maven archetype生成的默认项目名称
- node.js - 无需基于令牌的身份验证即可保护先前创建的 API
- bash - 将 ls 输出存储在变量中并拆分它不起作用