shrine
shrine copied to clipboard
content-disposition not being set
Can't tell what i'm doing wrong. Here's my shrine.rb below. The resulting content-dispostion stays default, which is inline; filename="Screenshot at Feb 09 10-09-57.png"; filename*=UTF-8''filenamepng
require "shrine/storage/s3"
s3_options = {
access_key_id: Rails.application.secrets.digitalocean_spaces_key,
secret_access_key: Rails.application.secrets.digitalocean_spaces_secret,
region: Rails.application.secrets.digitalocean_spaces_region,
endpoint: 'https://nyc3.digitaloceanspaces.com',
bucket: Rails.application.secrets.digitalocean_spaces_bucket,
}
Shrine.storages = {
# Shrine::Storage::S3.new(public: true, **s3_options)
cache: Shrine::Storage::S3.new(public: true, prefix: "cache", upload_options: {acl: "public-read"}, **s3_options),
store: Shrine::Storage::S3.new(public: true, prefix: "store", upload_options: {acl: "public-read"}, **s3_options),
}
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file
Shrine.plugin :uppy_s3_multipart # load the plugin
Shrine.plugin :backgrounding # adds background processing
Shrine.plugin :presign_endpoint, presign_options: -> (request) do
# Uppy will send the "filename" and "type" query parameters
filename = request.params["filename"]
type = request.params["type"]
{
content_disposition: ContentDisposition.attachment(filename), # download with original filename
content_type: type, # set correct content type
}
end
It would appear that it might get overwritten here when copying the cached file to permanent storage. You should be able to use the upload_options
plugin to set the attachment content disposition on upload to permanent storage.
As this doesn't appear to be a bug in the content_disposition
gem, I will move this issue to the Shrine repository.
It would appear that it might get overwritten here when copying the cached file to permanent storage. You should be able to use the
upload_options
plugin to set the attachment content disposition on upload to permanent storage.As this doesn't appear to be a bug in the
content_disposition
gem, I will move this issue to the Shrine repository.
require "shrine/storage/s3"
require "content_disposition"
s3_options = {
access_key_id: Rails.application.secrets.digitalocean_spaces_key,
secret_access_key: Rails.application.secrets.digitalocean_spaces_secret,
region: Rails.application.secrets.digitalocean_spaces_region,
endpoint: 'https://nyc3.digitaloceanspaces.com',
bucket: Rails.application.secrets.digitalocean_spaces_bucket,
}
Shrine.storages = {
# Shrine::Storage::S3.new(public: true, **s3_options)
cache: Shrine::Storage::S3.new(public: true, prefix: "cache", upload_options: {acl: "public-read", content_disposition: ContentDisposition.attachment("Download name")}, **s3_options),
store: Shrine::Storage::S3.new(public: true, prefix: "store", upload_options: {acl: "public-read", content_disposition: ContentDisposition.attachment("Download name")}, **s3_options),
}
# Check https://shrinerb.com/docs/plugins/activerecord for full list of plugins around ActiveRecord
# Check https://shrinerb.com/docs/external/extensions for full list of plugins/extensions
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file
Shrine.plugin :uppy_s3_multipart # load the plugin
Shrine.plugin :backgrounding # adds background processing
Updated to upload_options
to include ContentDisposition.attachment("Download name")
for both cache and store. Still cones up at inline.
Note: All i'm trying to do is create a link that'll allow my users to download the file instead of just viewing it. So if there's another solution to this, i'm very much open to it.
The code you posted looks like it should correctly set :content_disposition
to attachment. Are you able to reproduce this behaviour with AWS S3? It's possible this is an issue with Digital Ocean Spaces.
For me the last example works on AWS S3, so it seems it's an issue with DigitalOcean Spaces. Here is a self-contained example showing my recommended configuration:
require "shrine"
require "shrine/storage/s3"
require "content_disposition"
require "rack/test"
require "http"
s3_options = {
access_key_id: ENV.fetch("S3_ACCESS_KEY_ID"),
secret_access_key: ENV.fetch("S3_SECRET_ACCESS_KEY"),
region: ENV.fetch("S3_REGION"),
bucket: ENV.fetch("S3_BUCKET"),
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(public: true, prefix: "cache", **s3_options),
store: Shrine::Storage::S3.new(public: true, prefix: "store", **s3_options),
}
Shrine.plugin :presign_endpoint, presign_options: -> (request) do
# Uppy will send the "filename" and "type" query parameters
filename = request.params["filename"]
type = request.params["type"]
{
content_disposition: ContentDisposition.attachment(filename), # download with original filename
content_type: type, # set correct content type
}
end
Shrine.plugin :upload_options, store: -> (io, options) do
{ content_disposition: ContentDisposition.attachment(io.original_filename) }
end
# imitate Uppy's presign request
presign_endpoint = Shrine.presign_endpoint(:cache)
session = Rack::Test::Session.new(presign_endpoint)
session.get("/?filename=foo.txt&type=text/plain")
data = JSON.parse(session.last_response.body)
# imitate Uppy's upload request
HTTP.post(data["url"], form: data["fields"].merge(file: HTTP::FormData::Part.new("foobar")))
cached_file = Shrine.uploaded_file(id: data["fields"]["key"].match("cache/").post_match, storage: :cache, metadata: { filename: "foo.txt" })
attacher = Shrine::Attacher.new
attacher.attach_cached(cached_file)
attacher.promote
object = attacher.store.storage.object(attacher.file.id)
object.head.content_disposition # => "attachment; filename=\"foo.txt\"; filename*=UTF-8''foo.txt"