Remote URL · Shrine
The remote_url
plugin allows you to attach files from a remote
location.
plugin
:
remote_url,
max_size
:
20
*
1024
*
1024
Mục lục bài viết
Usage
The plugin will add the #<name>_remote_url
writer to your model, which
downloads the remote file and uploads it to temporary storage.
photo
.
image_remote_url =
"
http://example.com/cool-image.png
"
photo
.
image.
mime_type photo
.
image.
size photo
.
image.
original_filename
If you’re using Shrine::Attacher
directly, you can useAttacher#assign_remote_url
:
attacher
.
assign_remote_url(
"
http://example.com/cool-image.png
"
)
attacher
.
file.
mime_type attacher
.
file.
size attacher
.
file.
original_filename
Downloader
By default, the file will be downloaded using Down.download
from the Down
gem. This will use the Down::NetHttp backend by default, which is a wrapper
around open-uri.
You can pass options to the downloader via the :downloader
option:
attacher
.
assign_remote_url url,
downloader
:
{
headers
:
{
"
Authorization"
=>
"
Basic ..."
}
,
read_timeout
:
30
,
open_timeout
:
30
,
max_redirects
:
5
,
}
You can also change the downloader:
gem
"
http"
require
"
down/http"
plugin
:
remote_url,
downloader
:
-
>
(
url,
**
options)
{
Down
::
Http
.
download(
url,
**
options)
do
|
client
|
client
.
follow(
max_hops
:
2
)
.
timeout(
connect
:
2
,
read
:
2
)
end
}
Any Down::NotFound
and Down::TooLarge
exceptions will be rescued and
converted into validation errors. If you want to convert any other exceptions
into validation errors, you can raise them asShrine::Plugins::RemoteUrl::DownloadError
:
plugin
:
remote_url,
downloader
:
-
>
(
url,
**
options)
{
begin
RestClient
.
get(
url)
rescue
RestClient
::
ExceptionWithResponse
=>
error
raise
Shrine
::
Plugins
::
RemoteUrl
::
DownloadError
,
"
remote file not found"
end
}
Calling downloader
You can call the downloader directly with Shrine.remote_url
:
file
=
Shrine
.
remote_url(
"
https://example.com/image.jpg
"
)
file
You can pass additional options as well:
Shrine
.
remote_url(
"
https://example.com/image.jpg
"
,
headers
:
{
"
Cookie"
=>
"
..."
}
)
Uploader options
Any additional options passed to Attacher#assign_remote_url
will be forwarded
to Attacher#assign
(and Shrine#upload
):
attacher
.
assign_remote_url(
url,
metadata
:
{
"
mime_type"
=>
"
text/plain"
}
)
Maximum size
It’s a good practice to limit the maximum filesize of the remote file:
plugin
:
remote_url,
max_size
:
20
*
1024
*
1024
Now if a file that is bigger than 20MB is assigned, download will be terminated
as soon as it gets the “Content-Length” header, or the size of currently
downloaded content surpasses the maximum size. However, if for whatever reason
you don’t want to limit the maximum file size, you can set :max_size
to nil:
plugin
:
remote_url,
max_size
:
nil
Errors
If download errors, the error is rescued and a validation error is added equal
to the error message. You can change the default error message:
plugin
:
remote_url,
error_message
:
"
download failed"
plugin
:
remote_url,
error_message
:
-
>
(
url,
error)
{
I18n
.
t(
"
errors.download_failed"
)
}
Background
If you want the file to be downloaded from the URL in the background, you can
use the shrine-url storage which allows you to assign a custom URL as cached
file ID, and pair that with the backgrounding
plugin.
File extension
When attaching from a remote URL, the uploaded file location will inherit the
extension from the URL. However, some URLs might not have an extension. To
handle this case, you can use the infer_extension
plugin to infer the
extension from the MIME type.
plugin
:
infer_extension
Instrumentation
If the instrumentation
plugin has been loaded, the remote_url
plugin adds
instrumentation around remote URL downloading.
plugin
:
instrumentationplugin
:
remote_url
Downloading remote URLs will trigger a remote_url.shrine
event with the
following payload:
KeyDescription
:remote_url
The remote URL string:download_options
Any download options passed in:uploader
The uploader class that sent the event
A default log subscriber is added as well which logs these events:
Remote URL (1550ms) – {:remote_url=>"https://example.com/image.jpg",:download_options=>{},:uploader=>Shrine}
You can also use your own log subscriber:
plugin
:
remote_url,
log_subscriber
:
-
>
(
event)
{
Shrine
.
logger.
info JSON
.
generate(
name
:
event.
name,
duration
:
event.
duration,
**
event.
payload)
}
{"name":"remote_url","duration":5,"remote_url":"https://example.com/image.jpg","download_options":{},"uploader":"Shrine"}
Or disable logging altogether:
plugin
:
remote_url,
log_subscriber
:
nil