CSV 导入导出
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