2

I am trying to send a file through form_data and set the Content-Type header as the content type of the file (image/png, image/jpeg, etc.) instead of multipart/form-data.

I have tried multiple ways, but here is my method:

def fetch(url, body, headers, limit, use_ssl, use_file_content_type)
  raise HTTPRedirectLevelTooDeep, 'HTTP redirect too deep' if limit.zero?

  headers[:'Content-Type'] = body['file'].content_type if use_file_content_type

  uri = URI(url)
  request = Net::HTTP::Post.new(url)

  headers.each { |key, value| request[key.to_s] = value }

  form_data = body.to_a
  request.set_form form_data, 'multipart/form-data'
  
  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
    http.request(request)
  end

  case response
  when Net::HTTPSuccess     then response
  when Net::HTTPRedirection then fetch(response['location'], body, headers, limit - 1)
  else
    response.error!
  end
end

This sends the body just as I want it, but does not set the Content Type header correctly (it uses multipart/form-data). I also tried setting the header after setting the form data: request['Content-Type'] = body['file'].content_type right before http.request(request) but it sends Content-Type: application/x-www-form-urlencoded.

I also tried setting the header in the Net::HTTP::Post.new method, or moving everything after request = inside the Net::HTTP.start method, but it still does not work for me. I also tried using request.set_form form_data, body['file'].content_type, but that just says invalid enctype: image/jpeg

One thing that sent the headers correctly was replacing this:

form_data = body.to_a
request.set_form form_data, 'multipart/form-data'

with

request.body = body.to_json

But this does not send the file as the external API I'm using expects it.

Do you have any suggestions of how I could tackle this? Thanks!

Victor Motogna
  • 731
  • 1
  • 12
  • 22
  • 2
    If you're sending a file through form_data the content type is `multipart/form-data`, if you want to use the file's content type you have to send the file alone without using form data – Musa May 05 '21 at 17:18
  • In multipart form data each part of the request body has its own `Content-Disposition` and `Content-Type`. https://stackoverflow.com/questions/8659808/how-does-http-file-upload-work Doing this with with Net::HTTP instead of the libs like HTTParty or Faraday seems pretty machochistic though. Net::HTTP is auguably the worst part of the StdLib and extremely clunky to work with. – max May 06 '21 at 23:00

0 Answers0