Download Endpoint
The download_endpoint plugin provides a Rack app for
downloading uploaded files from specified storages. This can be useful when
files from your storage isn't accessible over URL (e.g. database storages) or
if you want to authenticate your downloads.
Global Endpoint
You can configure the plugin with the path prefix which the endpoint will be mounted on.
Shrine.plugin :download_endpoint, prefix: "attachments"The plugin adds a Shrine.download_endpoint method which returns a Rack
application that handles downloads using the rack_response plugin. You can
run this Rack app inside your app on the prefix that you specified:
# config/routes.rb (Rails)
Rails.application.routes.draw do
# ...
mount Shrine.download_endpoint => "/attachments"
endLinks to the download endpoint are generated by calling
UploadedFile#download_url instead of the usual UploadedFile#url.
uploaded_file.download_url #=> "/attachments/eyJpZCI6ImFkdzlyeTM..."Endpoint via Uploader
You can also configure the plugin in the uploader directly - just make sure to mount it via your Uploader-class.
class ImageUploader < Shrine
plugin :download_endpoint, prefix: "images"
end# config/routes.rb (Rails)
Rails.application.routes.draw do
# ...
mount ImageUploader.download_endpoint => "/images"
endHint: For shrine versions 2.x -> ensure that you don't include the plugin twice (globally and in your uploader class - see #408)
Calling from a controller
If you want to run additional code around the download (such as authentication),
mounting the download endpoint in your router might be limiting. You can instead
create a custom controller action and handle download requests there using
Shrine.download_response:
# config/routes.rb (Rails)
Rails.application.routes.draw do
# ...
get "/attachments/*rest", to: "downloads#image"
end# app/controllers/downloads_controller.rb (Rails)
class DownloadsController < ApplicationController
def image
# ... we can perform authentication here ...
set_rack_response ImageUploader.download_response(request.env)
end
private
def set_rack_response((status, headers, body))
self.status = status
self.headers.merge!(headers)
self.response_body = body
end
endIf you want to create an endpoint with a custom path, you can use the
rack_response plugin directly, which this plugin uses
internally.
Host
You can specify download URL host via the :host plugin option:
plugin :download_endpoint, host: "http://example.com"or by passing :host to UploadedFile#download_url:
uploaded_file.download_url(host: "http://example.com")
#=> "http//example.com/attachments/eyJpZCI6ImFkdzlyeTM..."Download options
If you want to pass additional options to Storage#open, you can do so via
:download_options:
plugin :download_endpoint, download_options: {
sse_customer_algorithm: "AES256",
sse_customer_key: "secret_key",
sse_customer_key_md5: "secret_key_md5",
}You can also specify a proc to generate download options dynamically:
plugin :download_endpoint, download_options: -> (uploaded_file, request) {
{
sse_customer_algorithm: "AES256",
sse_customer_key: "secret_key",
sse_customer_key_md5: "secret_key_md5",
}
}Performance considerations
Streaming files through the app might impact the request throughput, depending
on the web server you're using. So it's recommended to use a CDN, which can be
set via the :host option.
Alternatively, you can have the endpoint redirect to the direct file URL:
plugin :download_endpoint, redirect: trueYou can also specify a proc to generate your own redirect URL:
plugin :download_endpoint, redirect: -> (uploaded_file, request) do
uploaded_file.url(public: true)
endAd-hoc options
You can override any of the options above when creating the endpoint:
Shrine.download_endpoint(disposition: "attachment")Plugin options
| Name | Description | Default |
|---|---|---|
:disposition | Whether browser should render the file inline or download it as an attachment | inline |
:download_options | Hash of storage-specific options passed to Storage#open | {} |
:host | URL host that will be added to download URLs | nil |
:prefix | Path prefix prepended to download URLs | nil |
:redirect | Whether to redirect to uploaded files on the storage | false |