2016-04-21 40 views
0

我想从CSV文件导入数据,我不想保存该文件。我在这里发现了一个类似的问题:Ruby on Rails - Import Data from a CSV fileRails - 无法从CSV文件导入数据

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

我的格式如下:

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 %> 

在新页面中提交这种形式的调用创建动作,创建动作,然后调用行:

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 

其中'myfile'是params [:file]。

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

当寻找一个解决方案,我看到.path被使用。如果我将此行更改为csv_text = File.read(myfile.path),则会出现错误:“X.csv”的未定义方法`路径':字符串

任何人都可以帮忙吗?我觉得我必须非常接近解决方案,但是我只是在这两个错误之间继续前进。是否有可能从csv获取数据而不先保存它?

感谢您的时间

回答

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 
+0

http://api.rubyonrails.org/classes/ActionDispatch/Http/UploadedFile.html – amtest

+0

对不起,你能解释一切吗?我无法得到这个工作,.temp文件是未定义的文件,这是一个字符串 – JungleBook

0

与要记住的最重要的事情文件上传是,渲染表单的编码必须设置为multipart/form-data。我想你有这个维护。现在

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

在控制器,你将通过params访问IO对象。 params散列中的对象是IO子类的一个实例。

该对象的original_filename属性包含该文件在用户计算机上的名称和content_type属性,其中包含MIME类型的上载文件。

您可以将临时文件移动到您的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 

你,你可以利用在IO对象的属性tempfile。实际的文件可以通过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

+0

对不起,愚蠢的问题.. 我得到的错误:Errors:ENOENT ProductsController#upload 没有这样的文件或目录@ rb_sysopen -/<我的应用程序的路径> /public/uploads/X.csv 当你说我可以将临时文件移动到我公共目录中的目录时,你的意思是手动吗?程序中没有办法做到这一点? – JungleBook

+0

我想可能与 uploaded_io =参数有它[:文件] .tempfile csv_text = File.read(uploaded_io) 但需要测试正常 – JungleBook

+0

我已经更新了答案; – illusionist