class Net::HTTP::Post
Public Instance Methods
Similar to Net::HTTP::Post#set_form_data (in Ruby's stardard library), but set up file upload parameters using the appropriate HTTP/HTML Forms multipart format.
Arguments
- files_params
-
A hash of file upload parameters. The keys are parameter names, and the values are Net::HTTP::FileForPost instances. See that class documentation for more info about how POST file upload works.
- other_params
-
A hash of {key => value} pairs for the regular POST parameters, just like in set_form_data. Don't mix set_form_data and #set_multipart_data; they'll overwrite each other's work.
- boundary1, boundary2
-
A couple of strings which doesn't occur in your files. Boundary2 is only needed if you're using the multipart/mixed technique. The defaults should be OK for most cases.
Examples
Simplest case (single-parameter single-file), complete:
require 'net/http' require 'rubygems' require 'multipart' req = Net::HTTP::Post.new('/scripts/upload.rb') req.basic_auth('jack', 'inflamed sense of rejection') file = Net::HTTP::FileForPost.new('/tmp/yourlife.txt', 'text/plain') req.set_multipart_data({:poem => file}, {:author => 'jack', :user_agent => 'soapfactory'}) res = Net::HTTP.new(url.host, url.port).start do |http| http.request(req) end
Convoluted example:
pic1 = Net::HTTP::FileForPost.new('pic1.jpeg', 'image/jpeg') pic2 = Net::HTTP::FileForPost.new(pic2_io, 'image/jpeg') pic3 = Net::HTTP::FileForPost.new('pic3.png', 'image/png') pic1_t = Net::HTTP::FileForPost.new('pic1_thumb.jpeg', 'image/jpeg') pic2_t = Net::HTTP::FileForPost.new(pic2_t_io, 'image/jpeg') desc = Net::HTTP::FileForPost.new('desc.html', 'text/html', 'index.html') # remote fname req.set_multipart_data({:gallery_description => des, :pictures => [pic1, pic2, pic3], :thumbnails => [pic1_t, pic2_t]}, {:gallery_name => 'mygallery', :encoding => 'utf-8'})
# File multipart.rb, line 143 def set_multipart_data(files_params, other_params={}, boundary1="paranguaricutirimirruaru0xdeadbeef", boundary2="paranguaricutirimirruaru0x20132") self.content_type = "multipart/form-data; boundary=\"#{boundary1}\"" tmp = StringIO.new('r+b') # let's do the easy ones first other_params.each do |key,val| tmp.write "--#{boundary1}\r\n" tmp.write "content-disposition: form-data; name=\"#{key}\"\r\n" tmp.write "\r\n" tmp.write "#{val}\r\n" end # now handle the files... files_params.each do |name, file| tmp.write "\r\n--#{boundary1}\r\n" # no \r\n tmp.write "content-disposition: form-data; name=\"#{name}\"" if not file.is_a? Enumerable # single-file multipart is different if file.filename # right in content-dispo line tmp.write "; filename=\"#{file.filename}\"\r\n" else tmp.write "\r\n" end tmp.write "Content-Type: #{file.mimetype}\r\n" tmp.write "Content-Transfer-Encoding: binary\r\n" tmp.write "\r\n" tmp.write(file.read()) file.maybeclose else # multiple-file parameter (multipart/mixed) tmp.write "\r\n" tmp.write "Content-Type: multipart/mixed;" tmp.write " boundary=\"#{boundary2}\"\r\n" file.each do |f| tmp.write "\r\n--#{boundary2}\r\n" tmp.write "Content-disposition: attachment" if f.filename tmp.write "; filename=\"#{f.filename}\"\r\n" else tmp.write "\r\n" end tmp.write "Content-Type: #{f.mimetype}\r\n" tmp.write "Content-Transfer-Encoding: binary\r\n" tmp.write "\r\n" tmp.write(f.read()) f.maybeclose end tmp.write "\r\n--#{boundary2}--\r\n" end end tmp.write "--#{boundary1}--\r\n" tmp.flush self.content_length = tmp.size self.body_stream = tmp self.body_stream.seek(0) nil end