Tom, there is some sort of weird interaction effect on aolserver when doing tcl 
stuff and there is a large file as the temporary file.  Some cases cause the 
nsd process to bloat to the size of the memory.  I wasn't able to figure out 
why. I wasn't able to fix your ns_getform to not bloat.

However, I was able to copy Vlad's ns_parseformfile proc for use on aolserver 
from naviserver, and it doesn't bloat.

Here is the code for handling a large file uploaded as a file, rather than in 
memory:

        set type [ns_set iget [ns_conn headers] content-type]
        set form [ns_set create]
        ns_parseformfile $form $type
        array set formdata [ns_set array $form]
        puts "final array: [array get formdata]"


proc ns_parseformfile { form contentType } {

        set fp [ns_conn contentchannel]

    if { ![regexp -nocase {boundary=(.*)$} $contentType 1 b] } {
                puts "Warning: no MIME boundary"
        return
    }

    fconfigure $fp -encoding binary -translation binary
    set boundary "--$b"

    while { ![eof $fp] } {
        # skip past the next boundary line
        if { ![string match $boundary* [string trim [gets $fp]]] } {
            continue
        }

        # fetch the disposition line and field name
        set disposition [string trim [gets $fp]]
        if { ![string length $disposition] } {
            break
        }

        set disposition [split $disposition \;]
        set name [string trim [lindex [split [lindex $disposition 1] =] 1] \"]

        # fetch and save any field headers (usually just content-type for files)
        
        while { ![eof $fp] } {
            set line [string trim [gets $fp]]
            if { ![string length $line] } {
                break
            }
            set header [split $line :]
            set key [string tolower [string trim [lindex $header 0]]]
            set value [string trim [lindex $header 1]]
            
            ns_set put $form $name.$key $value
        }

        if { [llength $disposition] == 3 } {
            # uploaded file -- save the original filename as the value
            set filename [string trim [lindex [split [lindex $disposition 2] =] 
1] \"]
            ns_set put $form $name $filename

            # read lines of data until another boundary is found
            set start [tell $fp]
            set end $start
            
            while { ![eof $fp] } {
                if { [string match $boundary* [string trim [gets $fp]]] } {
                    break
                }
                set end [tell $fp]
            }
            set length [expr $end - $start - 2]

            # create a temp file for the content, which will be deleted
            # when the connection close.  ns_openexcl can fail, hence why 
            # we keep spinning

            set tmp ""
            while { $tmp == "" } {
                set tmpfile [ns_tmpnam]
                set tmp [ns_openexcl $tmpfile]
            }

            catch {fconfigure $tmp -encoding binary -translation binary}

            if { $length > 0 } {
                seek $fp $start
                ns_cpfp $fp $tmp $length
            }

            close $tmp
            seek $fp $end
            ns_set put $form $name.tmpfile $tmpfile

            if { [ns_conn isconnected] } {
                ns_atclose "ns_unlink -nocomplain $tmpfile"
            }

        } else {
            # ordinary field - read lines until next boundary
            set first 1
            set value ""
            set start [tell $fp]

            while { [gets $fp line] >= 0 } {
                set line [string trimright $line \r]
                if { [string match $boundary* $line] } {
                    break
                }
                if { $first } {
                    set first 0
                } else {
                    append value \n
                }
                append value $line
                set start [tell $fp]
            }
            seek $fp $start
            ns_set put $form $name $value
        }
    }
    close $fp
}


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to 
<[email protected]> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.

Reply via email to