Data URI
The data_uri plugin enables you to upload files as data URIs.
This plugin is useful for example when using HTML5 Canvas.
plugin :data_uriUsage
The plugin will add the #<name>_data_uri writer to your model, which parses
the given data URI string and uploads it to temporary storage:
photo.image_data_uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
photo.image.mime_type #=> "image/png"
photo.image.size #=> 43423If you're using Shrine::Attacher directly, you can use
Attacher#assign_data_uri:
attacher.assign_data_uri("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA")
attacher.file.mime_type #=> "image/png"
attacher.file.size #=> 43423Errors
If the data URI wasn't correctly parsed, an error message will be added to the attachment column. You can change the default error message:
plugin :data_uri, error_message: "data URI was invalid"
plugin :data_uri, error_message: ->(uri) { I18n.t("errors.data_uri_invalid") }
plugin :data_uri, error_message: ->(uri, error) { I18n.t("errors.data_uri.#{error.message}") }Maximum size
It's a good practice to limit the maximum size of the data URI content:
plugin :data_uri, max_size: 10*1024*1024 # 10 MBNow if content bigger than 10MB is assigned, parsing will fail the same way as for an invalid data URI. The size is calculated from the data URI before the content is decoded, so oversized content never gets loaded into memory. It's exact for base64 content, while for percent-encoded content the encoded length is used, which can overestimate.
Uploader options
Any options passed to Attacher#assign_data_uri will be forwarded to
Attacher#assign (and Shrine#upload):
attacher.assign_data_uri(uri, metadata: { "filename" => "nature.jpg" })File extension
A data URI doesn't convey any information about the file extension, so when
attaching from a data URI, the uploaded file location will be missing an
extension. If you want the upload location to always have an extension, you can
load the infer_extension plugin to infer it from the MIME type.
plugin :infer_extensionParsing data URI
If you just want to parse the data URI and create an IO object from it, you can
do that with Shrine.data_uri. If the data URI cannot be parsed, a
Shrine::Plugins::DataUri::ParseError will be raised.
# or YourUploader.data_uri(...)
io = Shrine.data_uri("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA")
io.content_type #=> "image/png"
io.size #=> 21
io.read # decoded contentWhen the content type is ommited, text/plain is assumed. The parser also
supports raw data URIs which aren't base64-encoded.
# or YourUploader.data_uri("...")
io = Shrine.data_uri("data:,raw%20content")
io.content_type #=> "text/plain"
io.size #=> 11
io.read #=> "raw content"You can also assign a filename:
io = Shrine.data_uri("data:,content", filename: "foo.txt")
io.original_filename #=> "foo.txt"Generating data URI
This plugin also adds UploadedFile#data_uri method, which returns a
base64-encoded data URI of the file content, and UploadedFile#base64, which
simply returns the file content base64-encoded.
uploaded_file.data_uri #=> "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
uploaded_file.base64 #=> "iVBORw0KGgoAAAANSUhEUgAAAAUA"Instrumentation
If the instrumentation plugin has been loaded, the data_uri plugin adds
instrumentation around data URI parsing.
# instrumentation plugin needs to be loaded *before* data_uri
plugin :instrumentation
plugin :data_uriParsing data URIs will trigger a data_uri.shrine event with the following
payload:
| Key | Description |
|---|---|
:data_uri | The data URI string |
:uploader | The uploader class that sent the event |
A default log subscriber is added as well which logs these events:
Data URI (5ms) – {:uploader=>Shrine}
You can also use your own log subscriber:
plugin :data_uri, log_subscriber: -> (event) {
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, uploader: event[:uploader])
}{"name":"data_uri","duration":5,"uploader":"Shrine"}
Or disable logging altogether:
plugin :data_uri, log_subscriber: nil