0
{
  "body": "Unsupported method.",
  "code": "400",
  "message": "",
  "res": {
    "connection": [
      "close"
    ],
    "content-length": [
      "19"
    ],
    "content-type": [
      "text;charset=ISO-8859-1"
    ],
    "date": [
      "Mon, 20 Sep 2021 05:37:36 GMT"
    ]
  }
}

Above error getting in Airbrake

uri = URI(URL it is constant)
req = Net::HTTP::Post.new(uri)
req.set_form(['upload', File.open("#{file_name}")], 'multipart/form-data')
req.set_form_data("mac" => mac)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
res = http.request(req)

case res
when Net::HTTPSuccess, Net::HTTPRedirection
  Rails.logger.info "File sent successgully"
  # OK
else
  Airbrake.notify("File transfer failed !", {code: res.code, message: res.message, body: res.body, res: res})
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
  • This isn't even remotely close to what you need to do to a file upload with Net::HTTP. [You need to create a separate part of the request body with a different content disposition where the file is added as binary](https://coderwall.com/p/c-mu-a/http-posts-in-ruby). Do yourself a favor and use a HTTP library like HTTParty instead of dealing with Net::HTTP which is very low level. – max Sep 20 '21 at 06:19
  • @max I think this should work HTTParty.post('URL', multipart: true, body: { body_stream: File.open('#{file_name}', 'r'), mac: '#{mac}' } ) – Aniket Sarkar Sep 20 '21 at 06:47
  • No - that will send the file as a key in the form data and the recipient will just get garbled garbage. As I have already written you're not even close. You need to use a separate part in form/multipart request for binary. – max Sep 20 '21 at 07:07
  • This is if you actually want to *transfer a file* - sending some JSON as a string is a completely different deal and doing it with 'multipart/form-data' is kind of stupid and you need to make sure to escape the content so that it doesn't contain things like ampersands which will lead to an unparseable request body. The "correct" way to do it is by sending a 'application/json' content type and putting the JSON as is in the request body. Where are you actually sending the data? – max Sep 20 '21 at 07:18
  • @AniketSarkar check this [post](https://stackoverflow.com/a/2603805/14475852) – Chandan Sep 20 '21 at 10:27

2 Answers2

2

This worked for me

  uri = URI.parse(RAKUTEN_URL)
    File.open("#{file_name}") do |transfile|
      Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
        req = Net::HTTP::Post::Multipart.new(
          uri.path,
          mac: encoded_mac,
          file: UploadIO.new(transfile, "multipart/formdata", File.basename("#{file_name}")),
        )
        response = http.request(req)
        case response
        when Net::HTTPSuccess, Net::HTTPRedirection
          #OK
          Rails.logger.info("File sent successfully. Don't panic its only for testing ! #{response}")
        else
          Airbrake.notify("File transfer failed ! #{response}")
        end
      end
    end
Yohann
  • 800
  • 10
  • 15
0

We had a similar use case and ended up using Net::HTTP::Post

...
req = Net::HTTP::Post.new(uri.path)
req.set_form(
  [
    ['mac', encoded_mac],
    [
      'file', 
      transfile, 
      { 
        filename: File.basename(file_name), 
        content_type: 'application/json' 
      }
    ]
  ],
  'multipart/form-data'
)
response = http.request(req)
...
Leo
  • 1,539
  • 17
  • 15