dslreports logo
site
 
    All Forums Hot Topics Gallery
spc

spacer




how-to block ads


Search Topic:
uniqs
1093
share rss forum feed


davidsmind
The Eye's Mind
Premium
join:2001-07-04
Canada

*Rails Beginner* Txt file upload to filesystem + DB

Hello all. I'm having some difficulty with the way that rails handles database writes vs. writes to hard drive. I can get my code to work to upload to the database, and to upload to the hard drive, but not both. I've tried replacing "after_save :store_doc" with just a direct call to the store_doc method, but that doesn't seem to work.

Can someone explain to me why this is? Without recommending a module to handle this, can someone guide me through writing a model that can accept a text upload, process the text into a DB and also write the file to a directory?

class Document < ActiveRecord::Base
        attr_accessible :body, :extension, :filename, :upload
 
        def upload=(incoming_file)
                        unless incoming_file.blank?
                        @incoming_file = incoming_file
              self.filename = incoming_file.original_filename
        self.extension = incoming_file.original_filename.split('.').last.downcase
                                if self.extension == 'txt'
                self.body = incoming_file.read
                                else
                                        self.body = 'wrong file type for direct uploading'
                                end
                        end
    end
 
#    def filename=(new_filename)
#        write_attribute("filename", sanitize_filename(new_filename))
#    end
 
    # File.join is a cross-platform way of joining directories;
    # we could have written "#{Rails.root}/public/doc_store"
    DOC_STORE = File.join Rails.root, 'public', 'doc_store'
 
     # where to write the first file to
    def document_filename
      File.join DOC_STORE, "#{id}.#{extension}"
    end
 
    # where to write the txt file to
    def document_txtfilenamehas_document
      File.join DOC_STORE, "#{id}.txt"
    end
 
    # return a path we can use in HTML for the docfile
    def document_html_path
      "/doc_store/#{id}.#{extension}"
    end
 
    # if a doc file exists, then we has a docfile
    def has_document?
      File.exists? document_filename
    end
 
after_save :store_doc
 
    private
 
                def store_doc
                logger.info "NOW inside store_doc"
                        if @incoming_file
                                #make the DOCSTORE dir if it doesn't already exist
                                FileUtils.mkdir_p DOC_STORE
                                #write out the data to the file
                                logger.info "write out the data to the file"
                                File.open(document_filename, 'wb') do |f|
                                        f.write(@incoming_file.read)
                                end
 
#                               @incoming_file = nil
                        end
                end
end
 


davidsmind
The Eye's Mind
Premium
join:2001-07-04
Canada

Keep in mind, with the above code, If I upload anything that ISNT a txt file, it gets saved to the hard drive no problem.



cdru
Go Colts
Premium,MVM
join:2003-05-14
Fort Wayne, IN
kudos:7
reply to davidsmind

I don't do rails, however I think your problem is likely on line 57. incoming_file.read likely act like a stream reader. Once you've read it in, you can't go back. So the data gets passed on to f.write, but then you no longer have a handle on the data to read/save it again.

Try reading the file into a local variable, then saving the local variable's data to disk and/or the database. This does have the negative consequence of increasing memory requirements of your program to that of the size of the file you are uploading twice (one for uploaded file buffer, one for the variable. If they are small files probably not an issue. Large files it could be.