Version 2 of File Upload with tcl's http

Updated 2005-02-27 04:57:33 by CMCc

CMcC 20050227: The process of uploading a file to a server entails encoding the file (and other form elements) as multipart/form-data. The code below handles that.

The second part of the upload will use http to send a -query with -type multipart/form-data, causing the client to POST the mime multipart/form-data to the server. Voila.

 # Provide multipart/form-data for http

 package provide form-data 1.0
 package require mime

 namespace eval form-data {}

 proc form-data::compose {partv {type multipart/form-data}} {
     upvar 1 $partv parts

     set mime [mime::initialize -canonical $type -parts $parts]
     set packaged [mime::buildmessage $mime]
     foreach part $parts {
         mime::finalize $part
     }
     mime::finalize $mime

     return $packaged
 }

 proc form-data::add_binary {partv name value type} {
     upvar 1 $partv parts
     set disposition "form-data; name=\"${name}\""
     lappend parts [mime::initialize -canonical $type \
                    -string $value \
                    -encoding binary \
                        -header [list Content-Disposition $disposition]]
 }

 proc form-data::add_field {partv name value} {
     upvar 1 $partv parts
     set disposition "form-data; name=\"${name}\""
     lappend parts [mime::initialize -canonical text/plain -string $value \
                        -header [list Content-Disposition $disposition]]
 }

 proc form-data::format {name value type args} {
     set parts {}
     foreach {n v} $args {
         add_field parts $n $v
     }
     add_binary parts $name $value $type
     return [compose parts]
 }

 if {[info script] eq $argv0} {

     # format a gif file upload according to the following form:
     #<FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="upload.php"> 
     #<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE=" "> 
     #<INPUT TYPE="HIDDEN" NAME="action" VALUE="1"> 
     #<INPUT TYPE="FILE" NAME="file1">
     #<INPUT TYPE="SUBMIT" VALUE="Host It"> <br> 
     #<INPUT TYPE="text" NAME="img_resize"  SIZE="4" MAXLENGTH="4">
     #</FORM>

     # get contents of the gif
     set fd [open ./logo125.gif]
     set image [read $fd]
     close $fd

     # set up other fields
     array set fields {
         MAX_FILE_SIZE " "
         action 1
         img_resize "100%"
     }

     # format the image and form
     puts [form-data::format file1 $image image/gif {expand}[array get fields]]
 }