downloading from S3 using original filename

2,127 views
Skip to first unread message

Alan Bullock

unread,
Jul 1, 2016, 2:38:47 PM7/1/16
to Shrine
Hi all

I am uploading directly to S3 using jquery-fileupload. The files are stored using a GUID key, but the same key is used for the filename when the user tries to download it. Is there any way I can specify that the original filename should be used instead?  I see that you can set "content-disposition: attachment; filename=foo.bar" but I am unsure how I can use shrine to set those headers using presigned uploads

Any help appreciated!

Alan 

Janko Marohnić

unread,
Jul 1, 2016, 11:27:20 PM7/1/16
to Alan Bullock, Shrine
Hi Alan,

The Aws::S3::Object#presigned_url method, which `Shrine::Storage::S3#url` delegates to (if :public option is not set), does accept a :response_content_disposition parameter, which you can set to whatever you want, regardless of how you uploaded the file.

disposition = "attachment; filename=#{user.avatar.original_filename.inspect}"
user.avatar.url(response_content_disposition: disposition)

This is the simplest way. (The reason why I'm using #inspect is to properly wrap it in double quotes.) Shrine does have default_url_options plugin to apply URL options automatically, but currently you cannot use it in a dynamic way depending on the filename.

Alternatively you can set the Content-Disposition on upload itself, for presigned uploads this means passing the :content_disposition option when generating presigns. You can do that by passing e.g. a "filename" query parameter when calling /presign URL in your JavaScript, and picking it up when generating presign options:

plugin :direct_upload, presign: true, presign_options: ->(request) do
  filename = request.params["filename"]
  {content_disposition: "attachment; filename=#{filename.inspect}"}
end

Regards,
Janko

--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine...@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/56690981-95e5-428b-8bb9-fe9317eccd1f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alan Bullock

unread,
Jul 3, 2016, 9:14:51 AM7/3/16
to Shrine
thanks Janko

I went with your second solution and it works beautifully :)

ja...@yourtradebase.com

unread,
Jul 6, 2017, 4:27:58 AM7/6/17
to Shrine, list...@gmail.com
Hi Janko,

Is there a way to presign files when not using direct_upload but storing files on S3?

Thanks


On Saturday, July 2, 2016 at 4:27:20 AM UTC+1, Janko Marohnić wrote:

Janko Marohnić

unread,
Jul 6, 2017, 5:42:47 AM7/6/17
to ja...@yourtradebase.com, Shrine, Alan Bullock
Yes, certainly, the `direct_upload` endpoint internally calls `Shrine::Storage::S3#presign`, which you can call directly:

require "securerandom"

id = SecureRandom.hex

presign = Shrine.storages[:cache].presign(id, {...})

presign.url    #=> "https://my-bucket.s3.amazonaws.com/..."

presign.fields #=> {...}


Kind regards,
Janko

--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine+unsubscribe@googlegroups.com.

To post to this group, send email to ruby-...@googlegroups.com.

robert...@citizensadvice.org.uk

unread,
Jul 18, 2019, 9:58:24 AM7/18/19
to Shrine
Hi,
Is there a way to set the S3 url response filename to the original filename using default url options?

I was using this code below, however, the download option is now deprecated and if I use the response_content_disposition option itself then this is replaced by this line https://github.com/shrinerb/shrine/blob/d48439e9ddf88ee0eb4fe494a3df6686cde8c3e0/lib/shrine/storage/s3.rb#L171

default_url_options = lambda do |io, **options|
  attachment_download_type
= options.key?(:download) ? "attachment" : "inline"
 
{
    response_content_disposition
: ContentDisposition.format(disposition: attachment_download_type, filename: io.original_filename),
    response_content_type
: io.mime_type
 
}
end
Shrine.plugin :default_url_options, cache: default_url_options, store: default_url_options


I'd like to set the original filename to be the original uploaded filename for S3 URLs by default

Thanks

Janko Marohnić

unread,
Jul 18, 2019, 10:11:48 AM7/18/19
to Shrine
That line in the S3 storage should simply URI-encode any UTF-8 characters from the :response_content_disposition string, which would otherwise cause aws-sdk-s3 to incorrectly sign the URL. What problems is it causing you?

Kind regards,
Janko

robert...@citizensadvice.org.uk

unread,
Jul 24, 2019, 4:15:44 AM7/24/19
to Shrine
Apologies, I had not finished debugging this issue. The problem I am having is trying to use the `default_url_options` plugin to set a) original uri-encoded filename and b) original mime-type when use S3 storage via the `response_content_disposition` and `response_content_type` options on either inline or attachment URLs. 

Previously I was using the code with default_url_options I mentioned in the previous message and I would like to do something like replacing the `download` option with the `response_content_disposition` option below as the download option is deprecated.

default_url_options = lambda do |io, **options|

  disposition
= options.fetch(:response_content_disposition, "inline")
 
{
    response_content_disposition
: ContentDisposition.format(disposition: disposition, filename: io.original_filename),

    response_content_type
: io.mime_type
 
}
end
Shrine.plugin :default_url_options, cache: default_url_options, store: default_url_options

However, the default_url_options plugin will overwrite the new `response_content_disposition` option - maybe this option hash merge could be the over way around so that I can replace an option? Or is there another way to do this by default? I'd like to keep the calling code as simple as possible, ie not have to move this into the places where `.url` is called.

Reply all
Reply to author
Forward
0 new messages