carrierwave + grape uploading an image from hashie mash - carrierwave

I have a hashie mash with filename, head, name, content-type, type, etc.
#<Hashie::Mash filename="modreal.jpg" head="Content-Disposition: form-data; name=\"image\"; filename=\"modreal.jpg\"\r\nContent-Type: image/jpeg\r\nContent-Length: 2406\r\n" name="image" tempfile=#<File:/var/folders/rh/rhhOCPJ9FOuqAbQjZPZh4k+++TI/-Tmp-/RackMultipart20131209-79188-1duiwwh> type="image/jpeg">
And I'm getting the following error when trying to give it to carrierwave.
ArgumentError:
expected instance of IO, StringIO, Tempfile or String, got Hashie::Mash
However when I just give the tempfile, it doesn't pass the extension whitelist. How can I make this work?

Related

How can I to make upload of file maintain your original `Content Type` to Amazon S3?

TL;DR
How can I to upload an image and maintain its original Content Type or, generate a signed or public URL that force a correct type for my file?
I explain more:
I have a problem with S3 (I really I'm using Minio, that is compatible with S3 protocol) in Rails app with
gem 'aws-sdk-s3', '~> 1.96'
I create the follow method to handle uploaded file (in Rails App) and send it to Minio.
def upload_file(file)
object_key = "#{Time.now.to_i}-#{file.original_filename}"
object = #s3_bucket.object(object_key)
object.upload_file(Pathname.new(file.path))
object
end
This is my uploaded file with correct Content-Type, before it was sent to Minio.
# file
#<ActionDispatch::Http::UploadedFile:0x00007f47918ef708
#content_type="image/jpeg",
#headers=
"Content-Disposition: form-data; name=\"images[]\"; filename=\"image_test.jpg\"\r\nContent-Type: image/jpeg\r\n",
#original_filename="image_test.jpg",
#tempfile=#<File:/tmp/RackMultipart20220120-9-gc3x7n.jpg>>
And here, is my file, with incorrect Type ("binary/octet-stream") on Minio
I need to send it to another service, and get the upload URL with correct Content-Type.
So, how can I to upload an image and maintain its original Content Type or, generate a signed or public URL that force a correct type for my file?
You could use the put_object method on the bucket instance that accepts a hash of options, one of which is content-type (Reference):
def upload_file(file)
object_key = "#{Time.now.to_i}-#{file.original_filename}"
#s3_bucket.put_object({
key: object_key,
body: Pathname.new(file.path),
content_type: "some/content_type"
})
end

How can I parse ruby json request

I'm using api request/response on my rails app. To update avatar i've got this request(i took it from development.log file)
Started PUT "/user/avatars.json" for 127.0.0.1 at 2017-07-18 11:47:57 +0300
Processing by AvatarsController#update as JSON
Parameters: {"avatar"=>#<ActionDispatch::Http::UploadedFile:0x007fe6cbedae18 #tempfile=#<Tempfile:/var/folders/n3/5_nb_zks2k91r5ngcmb4fm9r0000gn/T/RackMultipart20170718-26576-1vss7hh.png>, #original_filename="Снимок экрана 2017-07-16 в 21.55.05.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"avatar\"; filename=\"\xD0\xA1\xD0\xBD\xD0\xB8\xD0\xBC\xD0\xBE\xD0\xBA \xD1\x8D\xD0\xBA\xD1\x80\xD0\xB0\xD0\xBD\xD0\xB0 2017-07-16 \xD0\xB2 21.55.05.png\"\r\nContent-Type: image/png\r\n">}
Now, I need to send this request from POSTMAN application. But it uses ruby syntax like =>. How can I convert it to json to use in POSTMAN?
http://3dml.free.fr/rubyhashconverter/
I don't know if you need to do it within your code or not, but the above is an online converter, takes ruby hash syntax (old and new) and gives valid JSON.
JSON doesn't support binary data(images). So in order to pass the image, you need to convert image to base64 string and use it in JSON.

How to get file content from post rails

I have a client in java that sends form post requests with video file.
I get in the server following POST:
Parameters: {"video"=>#<ActionDispatch::Http::UploadedFile:0x007f26783b49d0
#original_filename="video", #content_type=nil,
#headers="Content-Disposition: form-data; name=\"video\"; filename=\"video\"\r\n",
#tempfile=#<Tempfile:/tmp/RackMultipart20160405-3-106c9nr>>, "id"=>"36"}
I am trying to save the file to s3 using following lines:
I know the connection and actual saving works because I tried with base64 string as parameter and it worked well.
body = params[:video].tempfile
video_temp_file = write_to_file(body)
VideoUploader.new.upload_video_to_s3(video_temp_file, params[:id].to_s+'.mp4')
I see on s3 empty files or 24 bytes.
where do i do wrong?
Edit: I am using carrierwave:
def write_to_file(content)
thumbnail_file = Tempfile.new(['video','.mp4'])
thumbnail_file.binmode # note that the tempfile must be in binary mode
thumbnail_file.write content
thumbnail_file.rewind
thumbnail_file
end

Rails4 JSON Parameters Parse error while Create

I am building API for Android using RoR, I am getting the Parameters for creating an object from Android is like below,
{"company"=>"{\"description\":\"Description of the company\",\"name\":\"Google\"}", "location"=>"Bangalore", "display_photo"=>#<ActionDispatch::Http::UploadedFile:0xb12dfa8 #tempfile=#<Tempfile:/tmp/RackMultipart20141119-6448-ewg4bk>, #original_filename="Male-Face-A1-icon.png", #content_type="image/*", #headers="Content-Disposition: form-data; name=\"display_photo\"; filename=\"Male-Face-A1-icon.png\"\r\nContent-Type: image/*\r\nContent-Length: 15460\r\nContent-Transfer-Encoding: binary\r\n">}
But this line giving error when parsing
"company"=>"{\"description\":\"Description of the company\",\"name\":\"Google\"}"
Because, It should be like this for Rails,
"company"=>{"description":"Description of the company","name":"Google"}
How to achieve this in Rails...
Refer this link where Android is requesting to Rails Server,
Android Code
In you params:
"company"=>
is a hash key
"{\"description\":\"Description of the company\",\"name\":\"Google\"}"
is a string, hash value
[2] pry(main)> JSON.parse "{\"description\":\"Description of the company\",\"name\":\"Google\"}"
=> {"description"=>"Description of the company", "name"=>"Google"}
gives correct output

How to read form-data with ruby

In my controller the result of request.body.read is:
=============
--AJAX-----------------------1267183973160
Content-Disposition: form-data; name="1261400603_page_white_word.png"; filename="1261400603_page_white_word.png"
Content-Type: application/octet-stream
thefile
--AJAX-----------------------1267183973160
Content-Disposition: form-data; name="1261400536_page_white_excel.png"; filename="1261400536_page_white_excel.png"
Content-Type: application/octet-stream
thefile
--AJAX-----------------------1267183973160--
=============
It contains n form-data (2 in my example), my goal is to loop through the n form-data and get the data name, filename and a file uploaded, in my example I replaced the binary data by thefile.
here is the content of the params hash
{"action"=>"create", "controller"=>"photos", "1265144945_395.jpg"=>#<File:/var/folders/BT/BTpdsWBkF6myaI-sl3+1NU+++TI/-Tmp-/RackMultipart20100226-273-1un364r-0>}
Cheers
Have you considered using paperclip or attachment_fu? They are battle-tested and will do better than using request.body. In any case, you could parse request.body as follows but it's not the best solution.
inputs = request.body.read.split(/--ajax-+\d+-*/mi)
inputs.each do |input|
input.scan(/(.*)[\n\r]{2,4}(.*)/m) do |header, file|
header.scan(/name=["'](.*)["'];\s+filename=["'](.*)["']/) do |name, filename|
puts name
puts filename
end
puts file
end
end
Edit: So that params parsing is probably the job of Rack::Utils::Multipart.parse_mulitpart. One should probably reuse the regex's from the source of that to parse this a bit more robustly. Also, it looks like rack is creating a tmp file for you of some sort. Can you check the contents of that file?

Resources