Reputation: 4103
I'm using this code to create an authenticated Amazon Url http://developer.longtailvideo.com/trac/browser/testing/files/s3-generator.php
Is it possible to somehow let Amazon know that the file needs to be force-downloaded by adding a Content-Disposition header?
Upvotes: 2
Views: 4598
Reputation: 171
The current versions of the AWS SDK for both PHP and Ruby have method parameters that allow you to specific the content disposition header when generating a signed link.
PHP:
response - array - Optional - Allows adjustments to specific response headers. Pass an associative array where each key is one of the following: cache-control, content-disposition, content-encoding, content-language, content-type, expires. The
Options hash: :response_content_disposition (String) — Sets the Content-Disposition header of the response when performing an HTTP GET on the returned URL.
Upvotes: 2
Reputation: 56
After gathering the individual pieces of this puzzle, I was able to create this Ruby method that properly signs a query string url using the aws secret key.
My resources for this:
Also, the response back from S3 was helpful, because when I created a url with a bad signature, the response showed the string_to_sign that AWS S3 generated from deciphering the URL I generated. After a few iterations I was able to converge on the correct formatting of the string_to_sign and after that it was pretty standard stuff.
Here is the Ruby method:
##############################################################################
# Create a signed query-string URL that supports setting response headers
##############################################################################
def s3_signed_url(bucket, pathname, verb, content_md5=nil, content_type=nil, response_headers = {})
expires = Time.now + 5.minutes
response_headers_canonicalized = response_headers.sort_by{|key, value| key.downcase}.collect{|key, value| "#{key}=#{value}"}.join("&").to_s
string_to_sign = "#{verb.upcase}\n#{content_md5}\n#{content_type}\n#{expires.to_i}\n/#{bucket}/#{pathname}?#{response_headers_canonicalized}"
digest = OpenSSL::Digest::Digest.new('sha1')
hmac = OpenSSL::HMAC.digest(digest, aws_secret_key, string_to_sign)
signature = Base64.encode64(hmac).chomp
url = "http://s3.amazonaws.com/#{bucket}/#{pathname}?"
if response_headers.count > 0
response_headers.each do |key, value|
url += "#{key}=#{value}&"
end
end
url += "AWSAccessKeyId=#{aws_access_key}&Expires=#{expires.to_i}&Signature=#{CGI.escape(signature)}";
return url
end
And you call the method like this:
file_url_s3 = s3_signed_url(file_bucket, file_path, 'GET', nil, nil, {'response-content-disposition' => 'attachment'})
Upvotes: 4