lib/carrierwave/base64/base64_string_io.rb in carrierwave-base64-2.7.0 vs lib/carrierwave/base64/base64_string_io.rb in carrierwave-base64-2.8.0
- old
+ new
@@ -1,31 +1,58 @@
+require 'mimemagic'
+require 'mimemagic/overlay'
+
module Carrierwave
module Base64
+ # Class that decodes a base64 string, builds a StringIO for the
+ # decoded bytes, and extracts the file MIME type to build a file
+ # name with extension.
class Base64StringIO < StringIO
- attr_accessor :file_extension, :file_name
+ # @return [String] the file name without extension
+ attr_reader :file_name
+ # @return [String] the file extension for the uploaded file
+ attr_reader :file_extension
+
+ # Returns a StringIO with decoded bytes from the base64 encoded
+ # string and builds a file name with extension for the uploaded file,
+ # based on the MIME type specified in the base64 encoded string.
+ #
+ # @param encoded_file [String] the base64 encoded file contents
+ # @param file_name [String] the file name without extention
+ #
+ # @raise [ArgumentError] If the base64 encoded string is empty
+ #
+ # @return [StringIO] StringIO with decoded bytes
def initialize(encoded_file, file_name)
description, encoded_bytes = encoded_file.split(',')
raise ArgumentError unless encoded_bytes
raise ArgumentError if encoded_bytes.eql?('(null)')
@file_name = file_name
- @file_extension = get_file_extension description
bytes = ::Base64.decode64 encoded_bytes
+ @file_extension = get_file_extension description, bytes
super bytes
end
+ # Returns a file name with extension, based on the MIME type specified
+ # in the base64 encoded string.
+ #
+ # @return [String] File name with extention
def original_filename
File.basename("#{@file_name}.#{@file_extension}")
end
private
- def get_file_extension(description)
- content_type = description.split(';base64').first
- mime_type = MIME::Types[content_type].first
+ # Determine content type from input, with provided type as fallback
+ def get_file_extension(description, bytes)
+ detected_type = MimeMagic.by_magic(bytes)
+ content_type = (detected_type && detected_type.type) ||
+ description.split(';base64').first
+ mime_type = MIME::Types[content_type].last
unless mime_type
raise Carrierwave::Base64::UnknownMimeTypeError,
"Unknown MIME type: #{content_type}"
end
mime_type.preferred_extension