Mime Type is not extracted from data uri

418 views
Skip to first unread message

erik.da...@gmail.com

unread,
Oct 29, 2015, 9:46:42 AM10/29/15
to ruby-shrine

Hi,

I cannot get the data_ui plugin to work. Mime type doesn't seem to get extracted. I don't know if that's the root cause to the problem but maybe a clue to start the troubleshooting.

This base64 sample is from Wikipedia. Any help would be appreciated!

> chart = Chart.create { image_data_ui: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" }

=> #<ImageUploader::UploadedFile:0x007fd49e9fbd28 @data={"id"=>"548f586e43655d60057be7cb86c2b1907d0ca6a90a75ebb45aa0e0c3d078", "storage"=>"cache", "metadata"=>{"filename"=>nil, "size"=>84, "mime_type"=>nil, "width"=>5, "height"=>5}}, @id="548f586e43655d60057be7cb86c2b1907d0ca6a90a75ebb45aa0e0c3d078", @storage_key="cache", @metadata={"filename"=>nil, "size"=>84, "mime_type"=>nil, "width"=>5, "height"=>5}, @uploader=#<ImageUploader:0x007fd49e9fbc88 @storage=#<Shrine::Storage::FileSystem:0x007fd49c486a98 @subdirectory=#<Pathname:system/uploads/cache>, @directory=#<Pathname:public/system/uploads/cache>, @host=nil, @permissions=nil, @clean=true>, @storage_key=:cache>>

If I temporary disable mime type validation and let Shrine generate the versions...

MiniMagick::Error: `mogrify -resize 480x270> /var/folders/sk/jybpjlz139q0wm42rg5s4lrc0000gn/T/8e85200e2c52a77c0043578d1f5dd55621ed6b5e91a54422e1bf788fea5f20151029-27423-1wmtukq` failed with error:
mogrify
: IDAT: invalid distance too far back `/var/folders/sk/jybpjlz139q0wm42rg5s4lrc0000gn/T/8e85200e2c52a77c0043578d1f5dd55621ed6b5e91a54422e1bf788fea5f20151029-27423-1wmtukq' @ error/png.c/MagickPNGErrorHandler/1630.
mogrify: corrupt image `
/var/folders/sk/jybpjlz139q0wm42rg5s4lrc0000gn/T/8e85200e2c52a77c0043578d1f5dd55621ed6b5e91a54422e1bf788fea5f20151029-27423-1wmtukq' @ error/png.c/ReadPNGImage/3959.




class Chart < ActiveRecord::Base
  include
ImageUploader[:image]
end

class ImageUploader < Shrine
  include
ImageProcessing::MiniMagick

  plugin
:activerecord
  plugin
:data_uri
  plugin
:determine_mime_type
  plugin
:logging, logger: Rails.logger
  plugin
:remove_attachment
  plugin
:store_dimensions
  plugin
:validation_helpers
  plugin
:versions, names: [:original, :thumb]


 
Attacher.validate do
    validate_max_size
2.megabytes, message: 'is too large (max is 2 MB)'
    validate_mime_type_inclusion
[/^image/]
 
end


 
def process(io, context)
   
case context[:phase]
   
when :store
      thumb
= resize_to_limit!(io.download, 480, 270)
     
{ original: io, thumb: thumb }
   
end
 
end
end

Janko Marohnić

unread,
Oct 29, 2015, 5:03:45 PM10/29/15
to ruby-shrine, erik.da...@gmail.com
Hey Erik,

The reason why data URIs content type isn't extracted is because you also loaded the `determine_mime_type` plugin. Without this plugin Shrine still extracts the MIME type of the file, but only by the information that it's given. So, for a ActionDispatch::Http::UploadedFile it will read `#content_type`, and for a data URI it will extract the MIME type that you see. However, if you load this plugin, it will attempt to actually determine the MIME type by file contents, by default using the UNIX "file" utility.

The reason why the file utility didn't properly extract the MIME type is because you didn't give it a file. Shrine internally constructs an IO-like object from the given data URI and forwards it further, but the file utility will only be used if the object responds to "#path". I should probably make determine_mime_type plugin raise an error if "file" utility is configured, but the file doesn't respond to #path.

ImageMagick failed probably because the image isn't really a valid image.

erik.da...@gmail.com

unread,
Oct 29, 2015, 6:21:51 PM10/29/15
to ruby-shrine, erik.da...@gmail.com

Makes perfect sense Janko, thank you for explaining.

/Erik

Janko Marohnić

unread,
Oct 29, 2015, 8:06:42 PM10/29/15
to ruby-shrine, erik.da...@gmail.com
I added the abilty to determine_mime_type plugin when using the file utility to accept IO-like objects that aren't files.

erik.da...@gmail.com

unread,
Oct 30, 2015, 7:40:02 AM10/30/15
to ruby-shrine, erik.da...@gmail.com

That is even better :)

Unfortunately I cannot get it to work (I'm on HEAD). I have a test case for posting a data uri to my API controller that passes when I disable the determine_mime_type plugin. When I enable the plugin I get an exception.

I get the same error when posting to the controller from Postman (API testing tool). The API controller is very slim and just passes along the params to the new method of the model.

I don't know if this is a Open3 related issue or if it's Rails related?

  1) Error:
Api::V1::CreatingChartsTest#test_creates_valid_charts:
Encoding::UndefinedConversionError: "\x89" from ASCII-8BIT to UTF-8
   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/open3.rb:308:in `write'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/open3.rb:308:in `
block in capture2'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/open3.rb:199:in `popen_run'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/open3.rb:145:in `popen2'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/open3.rb:300:in `
capture2'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/determine_mime_type.rb:98:in `_extract_mime_type_with_file'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/determine_mime_type.rb:81:in `extract_mime_type'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:297:in `
extract_metadata'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/store_dimensions.rb:42:in `extract_metadata'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:337:in `_store'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/versions.rb:137:in `
_store'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:266:in `store'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:82:in `block in store'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:97:in `
block in log'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:151:in `block in benchmark'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:151:in `
benchmark'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:97:in `log'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/logging.rb:82:in `store'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:237:in `
upload'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:595:in `cache!'

   
/Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine.rb:490:in `assign'
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/data_uri.rb:66:in `
data_uri='
    /Users/erikdahlstrand/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/bundler/gems/shrine-b5c182f484aa/lib/shrine/plugins/data_uri.rb:44:in `image_data_uri='



132 runs, 283 assertions, 0 failures, 1 errors, 0 skips

erik.da...@gmail.com

unread,
Oct 30, 2015, 7:42:34 AM10/30/15
to ruby-shrine, erik.da...@gmail.com

For the record and to not confuse any other, there is a missing '/' in the data uri in my first post. The valid data uri looks like this:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==



Den torsdag 29 oktober 2015 kl. 14:46:42 UTC+1 skrev erik.da...@gmail.com:

Janko Marohnić

unread,
Oct 30, 2015, 7:47:31 AM10/30/15
to erik.da...@gmail.com, ruby-shrine
Thanks for reporting. Could you try to go to the determine_mime_type plugin, and add `binmode: true` as the second option (after `:stdin_data`) to Open3.capture2, and see if it works?

--
You received this message because you are subscribed to the Google Groups "ruby-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/b6f2f93a-68cf-440c-9b88-6a9c7707fbf1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

erik.da...@gmail.com

unread,
Oct 30, 2015, 8:06:17 AM10/30/15
to ruby-shrine, erik.da...@gmail.com

Yes, it's working with the `binmode: true` option.

/Erik

Janko Marohnić

unread,
Oct 30, 2015, 1:24:10 PM10/30/15
to ruby-shrine, erik.da...@gmail.com

erik.da...@gmail.com

unread,
Nov 1, 2015, 9:46:56 AM11/1/15
to ruby-shrine, erik.da...@gmail.com

Great! Thanks Janko.
Reply all
Reply to author
Forward
0 new messages