Discussion:
winhttp problem doing mulitpart/form-data
(too old to reply)
glenn
2005-07-06 16:16:09 UTC
Permalink
I need to upload files to an http server using multipart/form-data.
Copying from a browser reply to a form page, this seems to be the
example of what should be sent (caught with mozilla and live headers.)

POST /cgi-bin/upload-cgi.pl HTTP/1.1

... other headers snipped ...

Content-Type: multipart/form-data; boundary=19024605111143684786787635207
Content-Length: 497
--19024605111143684786787635207
Content-Disposition: form-data; name="info"

this is some info
--19024605111143684786787635207
Content-Disposition: form-data; name="file"; filename="afile"
Content-Type: application/octet-stream

hello, this is a small one line file
--19024605111143684786787635207


The above is well and good, it matches the RFC etc my problem is in getting
WinHTTP to do the above. I can set up the connection etc... get the needed
handles, and add the headers that I want but all that I seem to be able to
make work is this: (from the winhttp trace tool)

09:24:30.519 ::*0000001* :: <<<<-------- HTTP stream follows below
----------->>>>
09:24:30.519 ::*0000001* :: POST /cgi-bin/upload-cgi.pl HTTP/1.1
09:24:30.519 ::*0000001* :: Content-Type: multipart/form-data;
boundary=127651370705190000
09:24:30.519 ::*0000001* :: Content-Disposition: form-data; name="info"
09:24:30.519 ::*0000001* :: Content-Disposition: form-data; name="file";
filename="junk.dat"
09:24:30.519 ::*0000001* :: Content-Type: application/octet-stream
09:24:30.519 ::*0000001* :: User-Agent: WebStream Service
09:24:30.519 ::*0000001* :: Host: 10.0.0.199
09:24:30.519 ::*0000001* :: Content-Length: 689
09:24:30.519 ::*0000001* :: Connection: Keep-Alive
09:24:30.519 ::*0000001* ::
09:24:30.519 ::*0000001* ::
09:24:30.519 ::*0000001* :: <<<<-------- End
--------------------------------->>>>

and the file data

09:24:30.519 ::*0000001* :: <<<<-------- HTTP stream follows below
----------->>>>
09:24:30.519 ::*0000001* :: 0 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 1 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 2 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 3 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 4 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 5 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 6 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 7 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 8 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* :: 9 junk.dat 0123456789 0123456789 0123456789
09:24:30.519 ::*0000001* ::
09:24:30.519 ::*0000001* :: <<<<-------- End
--------------------------------->>>>

Whenever I try to insert the text for the info field or a boundary line the
winhttp
coughs up an error. The examples are way too simple and the docs are mute
on this problem. If you can't insert boundary lines nor the intermediate
field data it seems that it is impossible to generate a valid
multipart/form-data POST using winhttp.

Is this the case for the current version of the winhttp library?
Stephen Sulzer
2005-07-10 22:26:32 UTC
Permalink
Hello,

WinHTTP can indeed do a multipart/form-data POST request. However, the
multipart/form-data format is an HTML/MIME-based specification, WinHTTP does
not "know" anything about this format.

To do a multipart/form-data request with WinHTTP, all the request data from
the first boundary line to the terminating boundary line, inclusive, must be
sent as the request body (i.e., as the data given to WinHttpSendRequest
and/or WinHttpWriteData).

The only HTTP request header given to WinHTTP is the "Content-Type:
multipart/form-data; boundary=..." header; all the headers contained within
the "form parts" are part of the request body.

So to send your example multipart/form-data request, the WinHTTP code would
look roughly like:


const wchar * ContentType =
L"Content-Type: multipart/form-data;
boundary=19024605111143684786787635207";

const char * MultipartRequestBody =
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"info\"\r\n"
"\r\n"
"this is some info\r\n"
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"afile\"\r\n"
"Content-Type: application/octet-stream\r\n"
"\r\n"
"hello, this is a small one line file\r\n"
"--19024605111143684786787635207--\r\n";


WinHttpSendRequest(hRequest, ContentType, wcslen(ContentType),
MultipartRequestBody,
strlen(MultipartRequestBody),
strlen(MultipartRequestBody),
dwContext);


Hope that helps.

- Stephen
glenn
2005-07-12 22:36:01 UTC
Permalink
Post by Stephen Sulzer
Hello,
WinHTTP can indeed do a multipart/form-data POST request. However, the
multipart/form-data format is an HTML/MIME-based specification, WinHTTP does
not "know" anything about this format.
To do a multipart/form-data request with WinHTTP, all the request data from
the first boundary line to the terminating boundary line, inclusive, must be
sent as the request body (i.e., as the data given to WinHttpSendRequest
and/or WinHttpWriteData).
multipart/form-data; boundary=..." header; all the headers contained within
the "form parts" are part of the request body.
So to send your example multipart/form-data request, the WinHTTP code would
const wchar * ContentType =
L"Content-Type: multipart/form-data;
boundary=19024605111143684786787635207";
const char * MultipartRequestBody =
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"info\"\r\n"
"\r\n"
"this is some info\r\n"
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"afile\"\r\n"
"Content-Type: application/octet-stream\r\n"
"\r\n"
"hello, this is a small one line file\r\n"
"--19024605111143684786787635207--\r\n";
WinHttpSendRequest(hRequest, ContentType, wcslen(ContentType),
MultipartRequestBody,
strlen(MultipartRequestBody),
strlen(MultipartRequestBody),
dwContext);
Hope that helps.
- Stephen
Your solution seems to work although I find it a bit counter intuitive.
Still having a problem with my cgi script but that is the stuff of another
question another time.

Thanks for the help.

glenn

Loading...