Tuesday 22 November 2011

Rails: Simple File upload

Inspired from Paperclip, I always wanted to have a simple file upload solution in Rails, which doesn't require any thumbnail generation. Here it's:

app/models/post.rb

  attr_accessor :data
  FOTO_DIR = File.join(Rails.root, 'public/photos')
  FOTO_PATH = File.join(FOTO_DIR, ':id/:filename')
  ALLOWED_TYPES = ['image/jpg', 'image/jpeg', 'image/png']

  validates :data_filename, :presence => true
  validates :data_size, :inclusion => { :in => 0..(5.megabytes) }, :allow_blank => true
  validates :data_content_type, :inclusion => { :in => ALLOWED_TYPES }, :allow_blank => true

  after_save :save_data_to_file

  def data=(file)
    return nil if file.blank?
    @data = file.path # temp file path
    self.data_filename = file.original_filename.to_s
    self.data_content_type = file.content_type.to_s
    self.data_size = file.size.to_i
    self.data_dimension = get_geometry(file)
  end

  def path
    fpath = FOTO_PATH.dup
    fpath.sub!(/:id/, self.id.to_s)
    fpath.sub!(/:filename/, self.data_filename)
    fpath
  end

  def url
    path.sub("#{Rails.root}/public", "")
  end

private

  def save_data_to_file
    return true if self.data.nil?
    ensure_dir(FOTO_DIR)
    ensure_dir(File.join(FOTO_DIR, self.id.to_s))
    Rails.logger.info "Saving file: #{self.path}"
    FileUtils.cp(self.data, self.path)
    true
  end

  def ensure_dir(dirname = nil)
    raise "directory path cannot be empty" if dirname.nil?
    unless File.exist?(dirname)
      FileUtils.mkdir(dirname)
    end
  end

  def get_geometry(file)
    `identify -format %wx%h #{file.path}`.strip
  end
Issuing Photo.create(:data => params[:photo]) should create the file in filesystem and save the record in DB, where params[:photo] is the file field value.

Its quite easy to make slight changes to this code piece to make it fit for your requirement , rather than writing patches/hacks to any gem.

No comments:

Post a Comment