Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><code>curb</code> looks like a great solution, but in case it doesn't meet your needs, you <em>can</em> do it with <code>Net::HTTP</code>. A multipart form post is just a carefully-formatted string with some extra headers. It seems like every Ruby programmer who needs to do multipart posts ends up writing their own little library for it, which makes me wonder why this functionality isn't built-in. Maybe it is... Anyway, for your reading pleasure, I'll go ahead and give my solution here. This code is based off of examples I found on a couple of blogs, but I regret that I can't find the links anymore. So I guess I just have to take all the credit for myself...</p> <p>The module I wrote for this contains one public class, for generating the form data and headers out of a hash of <code>String</code> and <code>File</code> objects. So for example, if you wanted to post a form with a string parameter named "title" and a file parameter named "document", you would do the following:</p> <pre><code>#prepare the query data, headers = Multipart::Post.prepare_query("title" =&gt; my_string, "document" =&gt; my_file) </code></pre> <p>Then you just do a normal <code>POST</code> with <code>Net::HTTP</code>:</p> <pre><code>http = Net::HTTP.new(upload_uri.host, upload_uri.port) res = http.start {|con| con.post(upload_uri.path, data, headers) } </code></pre> <p>Or however else you want to do the <code>POST</code>. The point is that <code>Multipart</code> returns the data and headers that you need to send. And that's it! Simple, right? Here's the code for the Multipart module (you need the <code>mime-types</code> gem):</p> <pre><code># Takes a hash of string and file parameters and returns a string of text # formatted to be sent as a multipart form post. # # Author:: Cody Brimhall &lt;mailto:brimhall@somuchwit.com&gt; # Created:: 22 Feb 2008 # License:: Distributed under the terms of the WTFPL (http://www.wtfpl.net/txt/copying/) require 'rubygems' require 'mime/types' require 'cgi' module Multipart VERSION = "1.0.0" # Formats a given hash as a multipart form post # If a hash value responds to :string or :read messages, then it is # interpreted as a file and processed accordingly; otherwise, it is assumed # to be a string class Post # We have to pretend we're a web browser... USERAGENT = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6" BOUNDARY = "0123456789ABLEWASIEREISAWELBA9876543210" CONTENT_TYPE = "multipart/form-data; boundary=#{ BOUNDARY }" HEADER = { "Content-Type" =&gt; CONTENT_TYPE, "User-Agent" =&gt; USERAGENT } def self.prepare_query(params) fp = [] params.each do |k, v| # Are we trying to make a file parameter? if v.respond_to?(:path) and v.respond_to?(:read) then fp.push(FileParam.new(k, v.path, v.read)) # We must be trying to make a regular parameter else fp.push(StringParam.new(k, v)) end end # Assemble the request body using the special multipart format query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--" return query, HEADER end end private # Formats a basic string key/value pair for inclusion with a multipart post class StringParam attr_accessor :k, :v def initialize(k, v) @k = k @v = v end def to_multipart return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n" end end # Formats the contents of a file or string for inclusion with a multipart # form post class FileParam attr_accessor :k, :filename, :content def initialize(k, filename, content) @k = k @filename = filename @content = content end def to_multipart # If we can tell the possible mime-type from the filename, use the # first in the list; otherwise, use "application/octet-stream" mime_type = MIME::Types.type_for(filename)[0] || MIME::Types["application/octet-stream"][0] return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{ filename }\"\r\n" + "Content-Type: #{ mime_type.simplified }\r\n\r\n#{ content }\r\n" end end end </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload