rootstrap / active-storage-base64

Base64 support for ActiveStorage
https://rootstrap.com
MIT License
161 stars 16 forks source link

ArgumentError - missing keyword: io: #25

Closed atebit closed 5 years ago

atebit commented 5 years ago

Any idea why I would be getting this error?

.attach(data: params["base64mp3"], filename: "Testfile..")

I see where your library turns data into [:io] but I don't get why it would error out...

atebit commented 5 years ago

If this doesn't work, my other option is to manually put on s3 like so...

def attach_audio( base64mp3, guid_filename )
  # filename
  data_parts = base64mp3.match(/\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m) || []
  extension = MIME::Types[data_parts[1]].first.preferred_extension
  filename = guid_filename << ".#{extension}"

  # blob to file conversion
  data_index = data.index('base64') + 7
  filedata = data.slice(data_index, data.length)
  decoded_file = Base64.decode64(filedata)

  # connect to s3
  s3 = Aws::S3::Resource.
    region: ENV['AWS_REGION'],
    access_key_id: ENV['AWS_KEY'],
    secret_access_key: ENV['AWS_SECRET']
  )
  bucket_name = ENV['AWS_BUCKET']
  bucket = s3.bucket( bucket_name )
  response = s3.bucket( bucket_name ).object( filename ).put(body:decoded_file, acl: 'public-read')
  url = s3.bucket( bucket_name ).object( filename ).public_url
  return url
end
atebit commented 5 years ago

Actually, the raw s3 thing works just fine, nvmd...

archonic commented 5 years ago

This is a valid issue. I've noticed that in development and production, this works:

doc.images.attach(data: upload_params[:file], filename: "#{doc.id}_#{Time.current.to_i}" )

But the same code raises ArgumentError: missing keyword: io in rspec. Any idea why?

Innarticles commented 5 years ago

@atebit Please how are you able to resolve this? Or it works only for S3? Having the same issue

info.featured_image1.attach(data: info_params[:data][:attributes][:featured_image1], filename: 'your_filename', content_type: 'image/jpg', identify: 'false') throws: ArgumentError (missing keyword: io): Please

santib commented 5 years ago

Hey @archonic @Innarticles @atebit The issue here is that the gem expects the base64 data to come with the Data URL "headers" https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs .

In other words the gem is expecting data:[data type];base64,[base64 data] and not just [base64 data] .

I understand we might need to either solve it or explain in the README why is it this way. You are welcome to open a PR if you want.

Babbz75 commented 5 years ago

Having the same problem but it's in the correct format i believe.

Error: missing keywords: io, filename

Format: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAA...

Code: @home_listing.images = { data: params['images'] }

santib commented 5 years ago

@Babbz75 Are you sure you used has_many_base64_attached for images in your home listing model instead of ActiveStorage has_many_attached?

Babbz75 commented 5 years ago

@santib I forgot to extract it from the array. For adding multiple images will we have to loop through the array and add them one by one?

Innarticles commented 5 years ago

@Babbz75 This worked for me. Provided you are passing the string correctly as now stated in the ReadMe

if !info_params[:data][:attributes][:images].empty? 
  info_params[:data][:attributes][:images]each { |image| @info.images.attach(data: image, filename: "1_#{Time.current.to_i}" ) }
end

Refactored!

Babbz75 commented 5 years ago

@Innarticles that makes sense, thanks guys!

santib commented 5 years ago

@Babbz75 You can do something like @home_listing.images = [{ data: [base64 data] }, { data: [base64 data] }] if you want.

@Innarticles Don't use for loops. https://github.com/rubocop-hq/ruby-style-guide#no-for-loops

Innarticles commented 5 years ago

Lol. @santib I was just looking at refactoring that code. Thanks!!

Babbz75 commented 5 years ago

What I ended up with:

     if params['images'].present?
          index = 0

          @home_listing.images = params['images'].map do |image|
            index += 1
            { data: image, filename: "#{@home_listing.address} file#{index}" }
          end
        end

Thanks again!

Innarticles commented 5 years ago

@Babbz75 This works provided your provider (I assume its S3 or GCS ..) is configured to store the files in separate folders/keys, you might run into the files being replaced because they have similar names. ("../file#0", ".../file#1"} then ("../file#0", ".../file#1"} ... But I am not certain of the implication. Just something you should look out for.

Babbz75 commented 5 years ago

@Innarticles Ah yeah, it didn't locally but just in case I added in some unique data into the filename.