Monday, November 08, 2010 at 12:06 AM.

system.verbs.builtins.tcp.httpPostMultipart

on httpPostMultipart (apiurl, f, username="", password="", adrparams=nil, filePartName="media_file", adrCode=nil) {
	<<Changes
		<<6/10/09; 3:55:16 PM by DW
			<<New optional param, adrCode, returns the HTTP result code, 200, 301, 404, etc. Added so we can check the code from tumblr.newPost.
		<<5/1/09; 12:47:32 PM by DW
			<<Cribbed from pownce.newPost. Once and for all, a multipart file uploader that can be reused.
	local (server, path, boundary);
	bundle { //set server, path
		local (urllist = string.urlsplit (apiurl));
		server = urllist [2];
		path = urllist [3]};
	bundle { //build boundary
		local (i);
		boundary = "";
		for i = 1 to 5 {
			boundary = boundary + string.innerCaseName (states.nthState (random (1, 50)))};
		boundary = string.hashmd5 (boundary)};
	local (type = "multipart/form-data; boundary=" + boundary, body = "");
	bundle { //build body
		local (indentlevel = 0);
		on add (s) {
			body = body + string.filledstring ("\t", indentlevel) + s + "\r\n"};
		if adrparams != nil {
			local (adr);
			for adr in adrparams {
				add ("--" + boundary);
				add ("Content-Disposition: form-data; name=\"" + nameof (adr^) + "\"");
				add ("");
				add (adr^)}};
		bundle { //add the file
			if f != nil {
				local (type);
				add ("--" + boundary);
				add ("Content-Disposition: form-data; name=\"" + filePartName + "\"; filename=\"" + file.filefrompath (f) + "\"");
				bundle { //set type
					local (ext = string.lastfield (f, "."));
					type = "text/plain";
					try {type = user.webserver.prefs.ext2MIME.[ext]}};
				add ("Content-Type: " + type);
				add ("");
				add (string (file.readwholefile (f)))};
			add ("--" + boundary + "--")}};
	<<body = string.delete (body, sizeof (body) - 2, 2)
	<<wp.newtextobject (body, @scratchpad.body)
	local (result = tcp.httpclient ("POST", server, 80, path, datatype:type, data:body, debug:false, username:username, password:password, timeOutTicks:60*60*60));
	<<wp.newtextobject (result, @scratchpad.posttext)
	if adrCode != nil { //6/10/09 by DW
		adrCode^ = tcp.httpGetStatusCode (result)};
	return (string.httpResultSplit (result))}
<<bundle //test code
	<<local (f, apiurl, username, password, params)
	<<new (tabletype, @params)
	<<f = "ohio:Original.jpg"
	<<username = "davewinertest"
	<<password = system.temp.dwpw
	<<params.username = username
	<<params.password = password
	<<apiurl = "http://posterous.com/api/upload"
	<<httpPostMultipart (apiurl, f, "", "", adrparams:@params, filePartName:"media")
	<<apiurl = "http://twitpic.com/api/upload"
	<<httpPostMultipart (apiurl, f, "", "", adrparams:@params, filePartName:"media")



This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.