beniutek
beniutek

Reputation: 1767

upload / post stringIO as file

I want to upload a stringIO as a file to a server. I'm not using rails to make the request, just ruby and some gems. I have created a stringIO like below:

require 'rest-client'
require 'zip'

... some code
stream = Zip::OutputStream::write_buffer do |zip|
  ... code that download files and packs them
end

stream.rewind

RestClient.post('somepath', { file: stream.read }, headers)

RestClient is just some handy gem that makes it a bit easier to send http request. so my problem is that on the server side in the controller when I receive the request I get an error

ArgumentError - invalid byte sequence in UTF-8:
  activesupport (4.2.6) lib/active_support/core_ext/object/blank.rb:117:in `blank?'
  carrierwave (0.10.0) lib/carrierwave/sanitized_file.rb:127:in `is_path?'
  carrierwave (0.10.0) lib/carrierwave/sanitized_file.rb:93:in `size'
  carrierwave (0.10.0) lib/carrierwave/sanitized_file.rb:136:in `empty?'
  carrierwave (0.10.0) lib/carrierwave/uploader/cache.rb:119:in `cache!'
  carrierwave (0.10.0) lib/carrierwave/mount.rb:329:in `cache'
  carrierwave (0.10.0) lib/carrierwave/mount.rb:163:in `export='
  carrierwave (0.10.0) lib/carrierwave/orm/activerecord.rb:39:in `export='
  app/controllers/exports_controller.rb:17:in `upload'

(I'm using carrierwave to store the files)

I think that I'm not handling the stringIO properly but honestly don't exactly know how should I pass it to the post request so that it behaves like a file

any ideas?

Upvotes: 1

Views: 3574

Answers (1)

beniutek
beniutek

Reputation: 1767

turns out this was happening because I was not saving the zip as a file but used write_buffer that responds with stringIO.

stringIO read method returns a string that was uploaded to my controller and then I tried to save the file using carrierwave roughly like that:

... code in my controller
myObject = ObjectModel.find(params[:id])
myObject.fileUploader = StringIO.new(params[:file]) => this was the string i received from stringIO read method
myObject.save

but it won't work because StringIO objects don't have original_filename method anymore since Rails3 (As far as I understood from the carrierwave issue page)

The solutions was to create a wrapper around StringIO and add either an attribute or a method that is called original_filename afterwards file was being saved correctly.

I'm posting link to carrierwave wiki that deals with this:

https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Upload-from-a-string-in-Rails-3-or-later

and a sample wrapper like object

  class StringIOWrapper < StringIO
    attr_accessor :original_filename
  end

afterwards this will work

myObject.fileUploader = StringIOWrapper.new(params[:file])
myObject.save

Upvotes: 1

Related Questions