Reading blob audio data in Ruby - ruby-on-rails

I need to send the raw audio data that a user records in the browser to an API.
I'm sending the raw blob object via POST to my Rails backend. It looks like this when recieved.
{"blob"=>#<ActionDispatch::Http::UploadedFile:0x00007f83ad01a7d8 #tempfile=#<Tempfile:/var/folders/cc/f7_d06hs6psbcxl87nwzsplr0000gn/T/RackMultipart20201021-933-1xu271c>, #original_filename="blob", #content_type="audio/wav", #headers="Content-Disposition: form-data; name=\"blob\"; filename=\"blob\"\r\nContent-Type: audio/wav\r\n">, "controller"=>"audios", "action"=>"interview"}
How can I read the actual data and extract it (without headers) to send to the external service?

The ActionDispatch::Http::UploadedFile looks similar to an IO object, so you can probably just:
uploaded_file = params["blob"]
raw_string = uploaded_file.read # do what you want with the raw data

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

Creating tempfile and removing non-image data

Been having some difficulty with an attachment issue on my site. At the moment our iOS app is pointing at an API endpoint for attachments, and sending a request similar to this:
POST /api/v2/attachments HTTP/1.1
--Boundary+0xAbCdEfGbOuNdArY
Content-Disposition: form-data; name="attachment"; filename="attachment.jpg"
Content-Type: image/jpeg
...image data...
--Boundary+0xAbCdEfGbOuNdArY--
Now, the request succeeds and the image is in fact uploaded, but it's turning out to be an invalid image because the boundary data is written to file. It basically looks like this:
file = Tempfile.new('attachment')
attachment_data = request.body.read
attachment_data.force_encoding('UTF-8')
file << attachment_data
attachment.asset = file
attachment.save!
Obviously request.body.read is including the entire request, Boundaries and all. We do actually have a stripping method that runs through each line of the file and strips out non-image data, but that's obviously not performant at all.
In an ideal world, we would just be getting the image data itself and using that to populate the tempfile, but I'm afraid I'm completely stumped about the best way to go about that.
Thoughts welcome. Thank you!

Get request response is in weird format

I send a get request to a local (separate from app) jetty web server
RestClient.get("ip/command/core/get-version", {})
Then I do a JSON.parse() on the response.
As a result I get
{"revision"=>"r2407", "full_version"=>"2.5 [r2407]", "full_name"=>" [r2407]", "version"=>"2.5"}
What's wrong? How do I turn it into a hash, so I can extract the full_version property?
String returned by service is html encoded. Try decoding it first:
JSON.parse(CGI.unescape_html(response_body))
Your JSON response looks to be encoded into HTML entities.
If you are using Ruby, try decoding the response using CGI.unescape_html prior to running JSON.parse. Running the result of that method through JSON.parse should give you your hash.

Resources