02 Mar 2006Upload a file via POST with Net::HTTP
To upload a file to a website I needed to supply the data with a content type of “multipart/form-data”. The Net:HTTP API does not offer any such functionality, it just accepts raw content data. So I needed to roll my own.
The “multipart/form-data” content type consists of a number of secions separated by --BOUNDARY\r\n
and terminated by BOUNDARY--\r\n
where BOUNDARY
is a string that does not appear in the content of any of the data transmitted to the server.
Each section represents a form field and contains a number of headers, a \r\n
, the content and finishes with a \r\n
. Normal form fields look like
Content-Disposition: form-data; name="mykey"
mydata
while file fields must include a few more headers.
Content-Disposition: form-data; name="mykey"; filename="filename"
Content-Transfer-Encoding: binary
Content-Type: text/plain
DATADATADATADATADATADATADATA...
To construct the parameters in ruby I use the following code;
To put it all together you need to join the parameters with boundary separators between each section. This can be done via
The last thing that needs to be done is to make sure that you set the HTTP Header Content-type
to multipart/form-data; boundary=BOUNDARY
.
A complete example that I extracted from code that uploads a css file to the w3c validator service is as follows.
It was a little bit painful to figure out “multipart/form-data” via Ethereal but relatively easy to implement. Hope this helps!
Update 3rd of October, 2006:
Slight correction supplied by Andrew Willis so that last boundary is ‘—’ + boundary + ‘—’
rather than just boundary + ‘—’
.