Implement content disposition in direct upload

This commit is contained in:
Peter Zhu 2019-07-28 16:13:22 -04:00
parent 599c170d8e
commit 9940c65a78
8 changed files with 85 additions and 9 deletions

View File

@ -1,3 +1,7 @@
* Set content disposition in direct upload using `filename` and `disposition` parameters to `ActiveStorage::Service#headers_for_direct_upload`.
*Peter Zhu*
* Allow record to be optionally passed to blob finders to make sharding
easier.

View File

@ -117,8 +117,10 @@ module ActiveStorage
end
end
def headers_for_direct_upload(key, content_type:, checksum:, **)
{ "Content-Type" => content_type, "Content-MD5" => checksum, "x-ms-blob-type" => "BlockBlob" }
def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, **)
content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
{ "Content-Type" => content_type, "Content-MD5" => checksum, "x-ms-blob-content-disposition" => content_disposition, "x-ms-blob-type" => "BlockBlob" }
end
private

View File

@ -104,8 +104,10 @@ module ActiveStorage
end
end
def headers_for_direct_upload(key, checksum:, **)
{ "Content-MD5" => checksum }
def headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, **)
content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
{ "Content-MD5" => checksum, "Content-Disposition" => content_disposition }
end
private

View File

@ -97,8 +97,10 @@ module ActiveStorage
end
end
def headers_for_direct_upload(key, content_type:, checksum:, **)
{ "Content-Type" => content_type, "Content-MD5" => checksum }
def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, **)
content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
{ "Content-Type" => content_type, "Content-MD5" => checksum, "Content-Disposition" => content_disposition }
end
private

View File

@ -28,7 +28,7 @@ if SERVICE_CONFIGURATIONS[:s3] && SERVICE_CONFIGURATIONS[:s3][:access_key_id].pr
assert_equal "text/plain", details["content_type"]
assert_match SERVICE_CONFIGURATIONS[:s3][:bucket], details["direct_upload"]["url"]
assert_match(/s3(-[-a-z0-9]+)?\.(\S+)?amazonaws\.com/, details["direct_upload"]["url"])
assert_equal({ "Content-Type" => "text/plain", "Content-MD5" => checksum }, details["direct_upload"]["headers"])
assert_equal({ "Content-Type" => "text/plain", "Content-MD5" => checksum, "Content-Disposition" => "inline; filename=\"hello.txt\"; filename*=UTF-8''hello.txt" }, details["direct_upload"]["headers"])
end
end
end
@ -62,7 +62,7 @@ if SERVICE_CONFIGURATIONS[:gcs]
assert_equal checksum, details["checksum"]
assert_equal "text/plain", details["content_type"]
assert_match %r{storage\.googleapis\.com/#{@config[:bucket]}}, details["direct_upload"]["url"]
assert_equal({ "Content-MD5" => checksum }, details["direct_upload"]["headers"])
assert_equal({ "Content-MD5" => checksum, "Content-Disposition" => "inline; filename=\"hello.txt\"; filename*=UTF-8''hello.txt" }, details["direct_upload"]["headers"])
end
end
end
@ -96,7 +96,7 @@ if SERVICE_CONFIGURATIONS[:azure]
assert_equal checksum, details["checksum"]
assert_equal "text/plain", details["content_type"]
assert_match %r{#{@config[:storage_account_name]}\.blob\.core\.windows\.net/#{@config[:container]}}, details["direct_upload"]["url"]
assert_equal({ "Content-Type" => "text/plain", "Content-MD5" => checksum, "x-ms-blob-type" => "BlockBlob" }, details["direct_upload"]["headers"])
assert_equal({ "Content-Type" => "text/plain", "Content-MD5" => checksum, "x-ms-blob-content-disposition" => "inline; filename=\"hello.txt\"; filename*=UTF-8''hello.txt", "x-ms-blob-type" => "BlockBlob" }, details["direct_upload"]["headers"])
end
end
end

View File

@ -31,6 +31,27 @@ if SERVICE_CONFIGURATIONS[:azure]
@service.delete key
end
test "direct upload with content disposition" do
key = SecureRandom.base58(24)
data = "Something else entirely!"
checksum = Digest::MD5.base64digest(data)
url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
uri = URI.parse url
request = Net::HTTP::Put.new uri.request_uri
request.body = data
@service.headers_for_direct_upload(key, checksum: checksum, content_type: "text/plain", filename: ActiveStorage::Filename.new("test.txt"), disposition: :attachment).each do |k, v|
request.add_field k, v
end
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request request
end
assert_equal("attachment; filename=\"test.txt\"; filename*=UTF-8''test.txt", @service.client.get_blob_properties(@service.container, key).properties[:content_disposition])
ensure
@service.delete key
end
test "upload with content_type" do
key = SecureRandom.base58(24)
data = "Foobar"

View File

@ -29,6 +29,30 @@ if SERVICE_CONFIGURATIONS[:gcs]
@service.delete key
end
test "direct upload with content disposition" do
key = SecureRandom.base58(24)
data = "Something else entirely!"
checksum = Digest::MD5.base64digest(data)
url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
uri = URI.parse url
request = Net::HTTP::Put.new uri.request_uri
request.body = data
@service.headers_for_direct_upload(key, checksum: checksum, filename: ActiveStorage::Filename.new("test.txt"), disposition: :attachment).each do |k, v|
request.add_field k, v
end
request.add_field "Content-Type", ""
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request request
end
url = @service.url(key, expires_in: 2.minutes, disposition: :inline, content_type: "text/html", filename: ActiveStorage::Filename.new("test.html"))
response = Net::HTTP.get_response(URI(url))
assert_equal("attachment; filename=\"test.txt\"; filename*=UTF-8''test.txt", response["Content-Disposition"])
ensure
@service.delete key
end
test "upload with content_type and content_disposition" do
key = SecureRandom.base58(24)
data = "Something else entirely!"

View File

@ -30,6 +30,27 @@ if SERVICE_CONFIGURATIONS[:s3]
@service.delete key
end
test "direct upload with content disposition" do
key = SecureRandom.base58(24)
data = "Something else entirely!"
checksum = Digest::MD5.base64digest(data)
url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
uri = URI.parse url
request = Net::HTTP::Put.new uri.request_uri
request.body = data
@service.headers_for_direct_upload(key, checksum: checksum, content_type: "text/plain", filename: ActiveStorage::Filename.new("test.txt"), disposition: :attachment).each do |k, v|
request.add_field k, v
end
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request request
end
assert_equal("attachment; filename=\"test.txt\"; filename*=UTF-8''test.txt", @service.bucket.object(key).content_disposition)
ensure
@service.delete key
end
test "upload a zero byte file" do
blob = directly_upload_file_blob filename: "empty_file.txt", content_type: nil
user = User.create! name: "DHH", avatar: blob