def export
   csv_string = FasterCSV.generate do |csv|
     csv << ["name","detail","price","num","category_id"]
     Product.find(:all).each do |p|
       csv << [p.name, p.detail, p.price, p.num, p.category_id]
     end
   end
   csv_string = NKF.nkf("-s",csv_string)
   send_data csv_string,  
   :type=>'text/csv;',:disposition => "attachment; filename=product.csv" 
 end

def self.import_db(file, model_str)
    field_names = eval(model_str).column_names
    field_names.delete("id")
    field_names.delete("deleted_at")
    params_value = {}
    file_path = "#{RAILS_ROOT}/tmp/csv/"
    Dir.mkdir(file_path,0777) unless File.exist?(file_path)
    file_name = "temp.csv"
    data_utf = file.read
    File.open(file_path + file_name , 'wb+') do |f|
      f.write(data_utf)
    end
    key_id = Time.now.strftime('%Y%m%d%H%M%S') 
    system(" nkf -w #{file_path + file_name} > #{file_path + key_id + file_name}")
    messages = []
    f_path = file_path + key_id + file_name
    index = -1  
    eval(model_str).transaction do
      FasterCSV.foreach(f_path) do |row|
        index += 1
        next if index == 0
        #开始垃圾处理,对象垃圾回收站,GC.start
        GC.start if index % 50 == 0
        row.each do |r|
          r = r.to_s.toutf8 unless r.blank?
      end
        field_names.each_with_index { |name, name_index| params_value["#{name}"] = row[name_index]}
        model = eval(model_str).new(params_value)
        if model.valid?
          model.save!
        else
          messages << "第#{index}行#{model.errors.full_messages}"           
        end
      end
    end
    FileUtils.rm_rf(file_path) if File.exists?(file_path)
    return messages
  end

 

def export    
    send_data Export.export_csv("Product"), :type=>'text/csv', 
                                            :disposition => "attachment",
                                            :filename => "product_#{Time.now.strftime('%Y%m%d%H%M%S')}.csv" 
  end

def self.export_csv(model)
    #动态取得model
    field_names = eval(model).column_names
    field_names.delete("id")
    field_names.delete("deleted_at")
    csv_string = FasterCSV.generate do |csv|
      #得到所有的modle字段
      csv << field_names
      eval(model).find(:all).each do |m|
        csv << field_names.collect {|name| m.send(name)}
      end
    end
    csv_string = NKF.nkf("-w", csv_string)
  end

 

 

使用<%= file_field_tag 'file' %>,在form表单中加入action指向csv_import,记得加上:enctype => "multipart/form-data"哦,不然不能上传文件。

<% form_for :attachment, :url => { :controller => "attachment", :action => "import_to_db" }, 
                                             :html => { :multipart => true } do |f| %>
    csv导入:<%= f.file_field :csv %>
    <br />
    <%= submit_tag "导入csv" %>
<% end %>

 

def self.import_to_db(file)
    file_path = "#{RAILS_ROOT}/tmp/csv/"  #创建文件夹 
    FileUtils.mkdir(file_path) if !File.exist?(file_path)
    #临时文件命名,不能有非法字符,比如"()"因为在linux下文件名不支持"()"等特殊符号   
    file_name = "temp.csv"
    begin
      data_utf = file.read#Iconv.conv("UTF-8//IGNORE","shift_jis//IGNORE",params[:csv_file].read)
      File.open(file_path + file_name , 'wb') do |f|
        f.write(data_utf)
        f.close
      end
    ensure  
      file.close
    end
    key_id = UUID.random_create().to_s 
    system("nkf -Lu -S -w80 #{file_path + file_name} > #{file_path + key_id + file_name}")
    messages = []
    f_path = file_path + key_id + file_name
    index = -1  
    Attachment.transaction do
      FasterCSV.foreach(f_path) do |row|
        flag = true
        index += 1
        next if index == 0
        GC.start if index % 50 == 0
        row.each do |r|
          r = r.to_s.toutf8 unless r.blank?
        end
        attachment = Attachment.new
        attachment.id = row[0]
        attachment.type = row[1]
        attachment.owner_id = row[2]
        attachment.url = row[3]
        attachment.name = row[4]
        attachment.created_at = row[5]
        attachment.updated_at = row[6]
        attachment.deleted_at = row[7]
        if attachment.save
          messages << "第#{index}行#{attachment.errors.full_messages}"
        end
      end
    end
    FileUtils.rm_rf(file_path) if File.exists?(file_path)
    return messages
  end