Martin Hart wrote:

>Hi all,
>
>I have a single HTML form which contains simple text controls as well as file 
>upload controls.  I had assumed that the CGI library would return me items of 
>type String for the text boxes and items of type Tempfile for the file upload 
>boxes....
>
>However, it appears (after searching the archives) that StringIO is used 
>instead of Tempfile on ruby 1.8 (in some cases and not others?), and that as 
>soon as you specify an enctype of multipart you never? receive Strings but 
>always receive either Tempfile or StringIO.
>
>This is what i really want from the CGI library:
>* CGI returns *everything* as a string except for file uploads - which are 
>returned as Tempfiles
>
>Assuming that I cannot have that :-) can somebody in the know please tell me 
>(or point me to some documentation)...
>
>1. how can I tell whether or not the supplied parameter was a file upload or 
>simple text that has been passed to me as a Tempfile/StringIO?  At the moment 
>I don't know whether to copy the file or not - because I don't know if it is 
>a valid file or just another parameter.
>
>2. do hidden controls work with multi-part forms?  there is some discussion of 
>them not working on the mailing list dating back to last November but I don't 
>know if that has been fixed or not.  My limited testing here indicates that 
>hidden parameters are ignored on multipart forms?
>
>3. why are all values expressed as Tempfile/StringIO when using a multipart 
>form?  Why not just have the file uploads as tempfiles?
>
>4. how does the CGI library determine whether or not to switch between 
>Tempfile/StringIO
>
>5. do I have to specifically close the IO object (assuming that one is 
>returned?) - or perhaps I do not have to close the StringIO but I do have to 
>close the Tempfile?
>
>6. are all of the form parameters in different tempfiles or are they all in 
>one?  Say i close the file after reading 1 argument ... does this mean that I 
>cannot read any more?
>
>Thanks for any help you can give me - I am pretty stuck on this.  If I get 
>code working with StringIO objects it seems to break when I submit large 
>files, and if I get code working with Tempfile it seems to break when I 
>submit small files :-)
>
>Cheers,
>Martin
>
>
>  
>
Here is the code that i use. Prob not the best but has worked for me so far.

class Upload
#{{{ -----------------------Uploads file to server from html 
form--------------------------
   
    #max size of file in bytes
    MAX_SIZE     = 100000
   
    #where the file goes / MUST HAVE WRITE PRIVS HERE
    PATH          = "/home/paul/web/"
   
    #how many file inputs - you can upload multiple files at once
    FILE_COUNT     = 3
   
    #what file types do we allow?
    CONTENT_TYPES= ['image/jpg','image/jpeg','image/gif','image/png']
   
   
   
   
    def initialize
       
        #how are things going?
        @status      = []
       
        if $form.isPost
           
            post
           
            print @status.join('<br/>')
           
            form
           
        else
       
       
            form
       
           
        end
           
    end
    def form
    #{{{
   
        puts '<form method="post" enctype="multipart/form-data">'
       
        FILE_COUNT.times do
       
            puts '<p/><input type="file" name="myfile">'

        end
           
         puts '<p/><input type=hidden name=upl value="upload">'         
         puts '<br/><input type=checkbox name="overwrite"/>Overwrite?'
         puts '<br/><input type="submit">'         
         puts '</form>'   
   
    end#}}}

   
    def post       
    #{{{
       
       
        oOverwrite = $cgi['overwrite'][0]
        bOverwrite = false
        overwrite = ''
       
        if oOverwrite
            overwrite = oOverwrite.read.chomp
            if overwrite == 'on' then bOverwrite = true end
        end

        $cgi['myfile'].each do |incoming|
           
            if incoming.size == 0
               
                @status<< "Ignoring empty field"
                next
           
            end
           
            if incoming.size > MAX_SIZE
               
                @status<< "Data too large for 
#{incoming.original_filename}(#{incoming.size} > #{MAX_SIZE})"
                next           
           
            end
           
            #need to strip :)...trailing space...ouch
            if not CONTENT_TYPES.include? incoming.content_type.strip
               
                @status<< "Type not allowed(type = 
#{incoming.content_type}) allowed content = #{CONTENT_TYPES.join(' | ')}"
                next           
           
            end           
           
            #puts incoming.filename
            # all should be ok to upload
           
            sfilename = incoming.original_filename.untaint
           
            #see if name has whacks...ie?
            rdash = sfilename.rindex('\\')           
            if rdash
                sfilename = sfilename[rdash+1,sfilename.length]
            end
           
            #physical path
            path      = PATH + $Domain + '/img/' + sfilename
       
           
            if File.exist? path           
                if bOverwrite
                    File.delete path
                else
                    @status<< "File already exists 
(#{incoming.original_filename})"
                    next
                end               
            end
           
            #write to file
            file = File.new(path.untaint,'w')               
            file << incoming.read
            file.close

            #path to link from web
            httpPath = "http://#{$Domain}/img/#{sfilename}"
           
            @status<< "Completed upload of <a target=_blank 
href='#{httpPath}'>#{httpPath}</a>"
        end   
   
    end#}}}

end#}}}
Upload.new