2

I want to upload a voice sound in my Rails project. The recording works fine to download, but I can't send the data to rails server.

recorder && recorder.exportWAV(function (blob) {
        var url = URL.createObjectURL(blob);
        console.log(url);

        $.ajax({
            type: "POST",
            url: "/voices",
            data: {voice: {sound: url}}
        });
    });

In server log there is a post data, but sound was not created.

Started POST "/voices" for ::1 at 2015-12-08 20:43:16 +0900
Processing by VoicesController#create as */*
  Parameters: {"voice"=>{"sound"=>"blob:http%3A//localhost%3A3000/3ad3859e-b960-44b8-ba18-20727e739bab"}}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  Profile Load (0.3ms)  SELECT  "profiles".* FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT 1  [["user_id", 1]]
   (0.2ms)  BEGIN
  SQL (0.5ms)  INSERT INTO "voices" ("sound", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["sound", nil], ["created_at", "2015-12-08 11:43:16.254713"], ["updated_at", "2015-12-08 11:43:16.254713"]]
   (0.6ms)  COMMIT
Completed 500 Internal Server Error in 135ms (ActiveRecord: 3.4ms)

How can I pass the sound blob data to rails server?

voices_controller.rb

class VoicesController < ApplicationController
    @voice = Voice.new(voice_params)

    respond_to do |format|
      if @voice.save
        format.html { redirect_to root_path, notice: 'voice was successfully created.' }
        format.json { render :show, status: :created, location: root_path }
      else
        format.html { render :new }
        format.json { render json: @voice.errors, status: :unprocessable_entity }
      end
    end

  def voice_params
    params.require(:voice).permit(:sound, :user_id)
  end
end

app/models/voice.rb

class Voice < ActiveRecord::Base
  belongs_to :phrase
  belongs_to :user
  mount_uploader :sound, SoundUploader
end

Another attempt

recorder && recorder.exportWAV(function (blob) {
    var url = URL.createObjectURL(blob);
    console.log(url);

    var formData = new FormData();
    formData.append('voice[sound]', url);

    $.ajax({
        type: "POST",
        url: "/voices",
        data: formData
    });
});

This codes ends up with a error Uncaught TYpeError: Illegal invocation.

ironsand
  • 14,329
  • 17
  • 83
  • 176
  • Your Controller code is not available and looking at the logs I am guessing that while saving the model, you are not passing the sound along to be saved. – Raman Dec 08 '15 at 11:54
  • `Completed 500 Internal Server Error in 135ms (ActiveRecord: 3.4ms)` could you attach the error message? – richfisher Dec 08 '15 at 12:04
  • I added the controller. Am I saving wrongly? – ironsand Dec 08 '15 at 12:05
  • @richfisher That was because I forgot to add a corresponding view template, there is any more `500 Internal Server Error`. – ironsand Dec 08 '15 at 12:07

1 Answers1

2

Not sure, if you are trying to post the data correctly or have your models setup properly. you need to save your audio as a file, using File.open(filename, w)

    SQL (0.5ms)  INSERT INTO "voices" ("sound", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["sound", nil], ["created_at", "2015-12-08 11:43:16.254713"], ["updated_at", "2015-12-08 11:43:16.254713"]]

The SQL, is suggesting, that nothing is getting passed to "sound" field.

  1. if you are passing it as a blob, you need to set the column accordingly, if not done entirely, however better option would be 2)
  2. Send and save the audio data as a file. Have a look at link

    formData.append('voice[sound]', url); # Comment this
    formData.append('voice[sound]', blob); # This will send the actual data to your server and not the blob url. then your carrierwave will have the file data, which it can save. 
    
Community
  • 1
  • 1
Sudipta Mondal
  • 2,550
  • 1
  • 19
  • 20
  • Sorry, that I didn't write enough information. I'm using a carrierwave to handle files. I still can't get how to handle the binary files. I'm very thankful if you could help me. – ironsand Dec 09 '15 at 02:16
  • have a look at the updated answer, you are sending a blob url, which only is existing in your browser, a better way should be to send the actual **blob** data to your rails application. – Sudipta Mondal Dec 09 '15 at 08:50
  • I changed the line, then I got `Uncaught TypeError: Illegal invocation` error. I'm stuck.. – ironsand Dec 09 '15 at 09:02
  • 1
    I guess, this is error with jQuery setting up headers incorrectly as processing the blob data, can you have a look at [link1](http://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery) and [link2](http://stackoverflow.com/questions/5392344/sending-multipart-formdata-with-jquery-ajax). you might need to add `processData: false` to your ajax call. – Sudipta Mondal Dec 09 '15 at 09:19
  • Finally! I just need to add `processData: false` and `contentType: false`, as the post that you showed me. Thanks! – ironsand Dec 11 '15 at 10:30