Rails - 无法从CSV文件导入数据

时间:2016-04-21 08:55:24

标签: ruby-on-rails csv import

我正在尝试从CSV文件导入数据,我不想保存文件。我在这里找到了类似的问题:Ruby on Rails - Import Data from a CSV file

但是,当我尝试使用此解决方案时,我收到错误。

我的表格如下:

Import a CSV file
<%= file_field_tag :file %>

<div class="actions form-group" id="button_text">
<p>
<%= button_tag(type: 'submit', class: "btn btn-primary button-submit") do %>
Submit
<% end %>

在新页面上,此表单的提交调用create动作,然后create action调用行:

Product.import(params[:file])

我的模型中有以下导入方法:

def self.import(myfile)
    require 'csv'    

    csv_text = File.read(myfile)
    csv = CSV.parse(csv_text, :headers => true)
    csv.each do |row|

    end
end

其中&#39; myfile&#39;是params [:file]。

我知道我还没有对数据做任何事情。我在第csv_text = File.read(myfile)行收到错误:没有这样的文件或目录@ rb_sysopen - X.csv

在寻找我见过的解决方案时,会使用.path。如果我将此行更改为csv_text = File.read(myfile.path),我会收到错误:未定义的方法`path&#39; for&#34; X.csv&#34;:String

有人可以帮忙吗?我觉得我必须非常接近解决方案,但我只是在这两个错误之间四处走动。是否可以从csv获取数据而不先保存它?

感谢您的时间

2 个答案:

答案 0 :(得分:2)

你可以这样做 .html.erb

<%= form_for(<object>, url: <path>, method: :post, remote: :true, html: {
  multipart: true, }) do |f| %>
    <input type="file" name="file_batch_upload"  accept=".csv />
<% end %>

//定义该功能

def self.import(file)
    require 'csv'    

    csv_text = File.read(file.tempfile)
    csv = CSV.parse(csv_text, :headers => true)
    csv.each do |row|
     //row["name"]
    end
end

答案 1 :(得分:0)

使用文件上传记住最重要的事情是渲染表单的编码必须设置为multipart/form-data。我想你已经保持了这一点。

<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'file' %>
<% end %>

现在,在控制器中,您可以通过IO访问params个对象。 params散列中的对象是IO的子类的实例。

该对象将包含original_filename属性,其中包含文件在用户计算机上的名称以及包含content_type类型上传文件的MIME属性。< / p>

您可以将临时文件移动到public目录中的某个目录,也可以简单使用并丢弃。

def upload
  uploaded_io = params[:file]

  # Moving the file to some safe place; as tmp files will be flushed timely
  File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
    file.write(uploaded_io.read)
  end
end

对您而言,您可以利用tempfile对象中的IO属性。实际文件可以通过tempfile访问器访问,但是为方便起见,它的一些界面可以直接使用。

所以,这应该有用

...
csv_text = File.read(file.tempfile)
...

更新

> uploaded_io = params[:file]
=> #<ActionDispatch::Http::UploadedFile:0x007f4154fe9a38
 @content_type="application/pdf",
 @headers="Content-Disposition: form-data; name=\"file\"; filename=\"3423loadshedding.pdf\"\r\nContent-Type: application/pdf\r\n",
 @original_filename="3423loadshedding.pdf",
 @tempfile=#<File:/tmp/RackMultipart20160421-14883-1lv0qtq.pdf>>

[2] pry(#<PostsController>)> uploaded_io.tempfile
=> #<File:/tmp/RackMultipart20160421-14883-1lv0qtq.pdf>

> uploaded_io.tempfile.class
=> Tempfile

错误

ProductsController#upload No such file or directory @ rb_sysopen - /<path to my app>/public/uploads/X.csv 

您需要先创建文件夹public/uploads

$ mkdir public/uploads

现在试试;该文件应该被移动。这是PaperclipCarrierwave管理上传文件的方式。