# use it like so: Net::HTTP.multi_post_form(url, params)

class Net::HTTP
  def self.multi_post_form(url, params)
    req = Post.new(url.path)
    req.multipart_params = params
    req.basic_auth url.user, url.password if url.user
    new(url.host, url.port).start {|http|
      http.request(req)
    }
  end
end
  
module Net
  class HTTP
    class Post
      def multipart_params=(param_hash={})
        boundary_token = [Array.new(8) {rand(256)}].join
        self.content_type = "multipart/form-data; boundary=#{boundary_token}"
        boundary_marker = "--#{boundary_token}\r\n"
        
        self.body = param_hash.map { |param_name, param_value|
          boundary_marker + text_to_multipart(param_name, param_hash.delete(param_name).to_s) unless param_value.respond_to?(:read)
        }.join('') 
        
        self.body += param_hash.map { |param_name, param_value|
          boundary_marker + file_to_multipart(param_name, param_value)
        }.join('') 
        
        self.body += "--#{boundary_token}--\r\n"
      end

    protected
  
      def file_to_multipart(key,file)
        filename = File.basename(file.path || file.base_uri.to_s)
        mime_type = "application/octet-stream"
        part = %Q|Content-Disposition: form-data; name=\"#{key}\"; filename="#{filename}"\r\n|
        part += "Content-Transfer-Encoding: binary\r\n"
        part += "Content-Type: #{mime_type}\r\n\r\n#{file.read}\r\n"
      end

      def text_to_multipart(key,value)
        "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n#{value}\r\n"
      end
    end
  end
end