USING HTTP PUT TO UPLOAD BINARY
AND TEXT DATA FROM THE IE CLIENT

By Peter A. Bromberg, Ph.D.

Peter Bromberg  

There must be at least two dozen "file upload" components out there, as well as about four or five "Script only" solutions. But the fact of the matter is, with HTTP 1.1 we have the HTTP "PUT" verb, which is not only extremely easy to use, but if you have the correct web server permissions set up and your web server accepts the "PUT" verb, there is really no need for any of this stuff at all!



You can do it yourself with no components other than the freely distributed MSXML parser and ADO, both of which should be already present on your client - side machine. If they aren't, you can get them for free from Microsoft.

What we'll do here is demonstrate the VBScript code required for a CLIENT - SIDE HTM page that will enable you to upload any type of file to your webserver at will. The only caution I would give you is that if HTTP PUT has been disabled on your webserver or you don't have the IIS or NTFS permissions to write a file to the webserver machine's filesystem, you will have to take care of that little problem yourself.

I'm going to provide a little narrative of how it works, so bear with me. When you're done reading, you should be able to copy the code block right out of this page, save it to your local machine webserver, and use it "right out of the box".

<script language=VBSCRIPT>
dim strURL
function sendit( sfileName, sType)
sData = getFileBytes(sfileName, sType)
sfileName= mid(sfileName, InstrRev(sFileName,"\")+1,len(sfileName))
dim xmlhttp
set xmlhttp=createobject("MSXML2.XMLHTTP.3.0")
strURL = "http://localhost/" & sFileName
msgbox "URL is: " & strURL
xmlhttp.Open "PUT", strURL, false
xmlhttp.Send sData
show.innerText= "Status: " & xmlhttp.statusText
set xmlhttp=Nothing
End function

sub showresult()
document.write "<CENTER>Take A look!<BR><A href=" & strURL & ">"& strURL & "</a></CENTER>"
end sub

function getFileBytes(flnm, sType)
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
if sType="on" then
objStream.Type = 1 ' adTypeBinary
else
objStream.Type = 2 ' adTypeText
objStream.Charset ="ascii"
end if
objStream.Open
objStream.LoadFromFile flnm
if sType="on" then
getFileBytes=objStream.Read
else
getFileBytes= objStream.ReadText
end if
objStream.Close
Set objStream = Nothing
end function
</script>

<TABLE align="center">
<TR><TD><input type=FILE id=filedata ></TD></TR>
<TR><TD><input type=submit onclick="Call sendit( filedata.value, filetype.value)"></TD></TR>
<TR><TD><input type=checkBox id=filetype checked >Type Binary (Uncheck for Type Text)</TD></TR>
<TR><TD><input type=button value = "SHOW IT" onclick ="showresult()"></TD></TR>
</TABLE>
<div id=show align="center"></div>

OK, Here is what's happening. At the bottom, inside the <TABLE> tags, we present ourselves with some formfields. First is a FILE type field that simply allows us to browse our filesystem, select the desired file to upload, and have it's full path and filename held in the "filetype.value" attribute. Next we have a SUBMIT control whose onClick event calls the "sendit" function in our script, passing in the info from the FILE field and the value of the next field, which is a checkbox that tells us whether we want to upload a binary type file (gif, jpeg, EXE, DOC, etc) or a Text type file (HTM, ASP, etc). Finally we have a button "SHOW IT" that simply creates a URL link to the uploaded file on the target server so we can look at it after we're done with our upload

Now lets breeze through the code: Function "Sendit" receives the file name and type (in this case simply whether the checkbox is "on"). It immediately calls the getFileBytes function, again passing in the "flnm" and "sType". Next, getFileBytes opens up an ADO Stream object to do the reading. (I wouldn't rely on Scripting.FileSystem to do my file reading here, although you are certainly welcome to try it - you'll need some Binary conversion functions).

If the sType is "on" (Binary) we set the Stream Type to 1 (adTypeBinary), otherwise we set it to 2 (adTypeText) and we also set the Charset to "ascii" (unless all your textfiles are Unicode, in which case you may have required this article to be translated for you).

We then Open our stream, and again, depending on the file type, we call the Read (for Binary) or the ReadText (for Text) method to get our file into the Stream. We assign the result to the function name as is typical with VB, close our stream, and we're done.

The next line " , sfileName= mid(sfileName, InstrRev(sFileName,"\")+1,len(sfileName)), simply parses out the name and extension of our file from the full path and name so that we can stick it on the end of our URL.

We open an instance of our trusty old XMLHTTP, stick the sFileName on the end of our URL (a "PUT" URL, unlike other URL's, must point to the actual HTTP URL+filename we want to write to ) , and finally we call the XMLHTTP Send method with sData as the payload. We show the XMLHTTP statusText by populating the <div> "Show" tag's innerText property with it, and we're done. All you'll need to do here is change the "http://localhost/" to the actual URL and virtual folder on your webserver where you want all these glorious files to be written to.

I am really sorry that this is all so simple, but -- IT IS! This ain't your Father's XML.



Peter Bromberg is an independent consultant specializing in distributed .NET solutionsa Senior Programmer /Analyst at in Orlando and a co-developer of the NullSkull.com developer website. He can be reached at info@eggheadcafe.com