I'm trying to create a signed URL of a file that can let the user download file from the S3 bucket.
I'm following this way written in docs.
The generated signature is working perfectly and it gets to download the file as well when a user visits the URL. The problem is that I want the name of the downloaded file to be custom.
For example: FileKey: tg6AbybBgFMidmKy5dz4vVXZ FileName: test.xlsx
The file is saved on S3 with the key and without the file extension.
So, when a user downloads the file, it's extensionless and hence unrecognized by OS. I want it to be downloaded with the FileName. I tried adding response-content-disposition in the query but it throws the error:
Below is the code I'm using right now.
# 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
I'm not using AWS SDK. I'm trying to do it on my own!
EDIT: Even after adding & which was missing, I was getting a signature mismatch.
