Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSTing file as multipart/form-data to a Rails API

RoR noob here... :)

I need to create a Rails API that clients can call and send an XML file through a POST request.

I've create my route like this:

  namespace :api do
      namespace :v1 do
        resource :report
      end
  end

and my controller like this:

class Api::V1::ReportsController < ApplicationController

  respond_to :xml

  def create
    @report_submission = ReportSubmission.create :login => params[:login],
                                                 :status => :success
    respond_with(@report_submission)
  end
end

What do I need to do in the controller to receive the XML file that the client will be posting, and then read is content so I can ultimately put it in the database?

How can I test that?

I've created a sandbox project to try this out and got stuck... no idea what to do next. I've pushed it up here:

https://github.com/claudiolassala/api-samples/

Any help will be just awesome! end

like image 716
Claudio Lassala Avatar asked Jul 23 '11 05:07

Claudio Lassala


People also ask

How do you send a file using multipart form data?

Multipart form data: The ENCTYPE attribute of <form> tag specifies the method of encoding for the form data. It is one of the two ways of encoding the HTML form. It is specifically used when file uploading is required in HTML form. It sends the form data to server in multiple parts because of large size of file.

What is multipart form data in API?

Multipart/Form-Data is a popular format for REST APIs, since it can represent each key-value pair as a “part” with its own content type and disposition. Each part is separated by a specific boundary string, and we don't explicitly need Percent Encoding for their values.

How does multipart file upload work?

Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.


1 Answers

After doing some more research, I've managed to get that working. I've updated my repository on GitHub with the solution.

The main changes were to modify my controller so to read the contents of the file being posted:

class Api::V1::ReportsController < ApplicationController

  respond_to :xml

  def create

    @report_submission = ReportSubmission.create :login => params[:login],
                                                 :status => :success,
                                                 :results => read_file_data(params[:reportxml])
    respond_with(@report_submission)
  end

  private
    def read_file_data(file)
      xml_contents = ""
      if file.respond_to?(:read)
        xml_contents = file.read
      elsif file.respond_to?(:path)
        xml_contents = File.read(file.path)
      else
        logger.error "Bad file_data: #{file.class.name}: #{file.inspect}"
      end
      xml_contents
    end
end

And I've fixed my Cucumber step that performs the post, changing it to this:

When /^I send a POST request containing the file$/ do
  @login = "some-login"
  @file_path = "#{::Rails.root.to_s}/features/step_definitions/test_report.xml"

  post "api/v1/report.xml?login=#{@login}",
       :reportxml => Rack::Test::UploadedFile.new(@file_path, 'text/xml')
end

Please let me know whether there's any better way to do this. Thanks!

like image 96
Claudio Lassala Avatar answered Oct 03 '22 19:10

Claudio Lassala