我正在尝试将一个csv文件上传到Rails并将其解析为db。我尝试使用Paw和Postman发送http请求,指定POST,附加csv文件,并将Content-Type指定为application / csv
请求标头:
POST /skate_parks/import HTTP/1.1
Content-Type: text/csv
Host: localhost:3000
Connection: close
User-Agent: Paw/2.3.4 (Macintosh; OS X/10.11.5) GCDHTTPRequest
Content-Length: 11663
Name,Address,Suburb,Postcode,State,Business Category,LGA,Region,
Aireys Inlet Skate Park,Great Ocean Road,Aireys Inlet,3231,VIC,Skate Parks,Surf Coast,Barwon S/W, etc...
控制器skate_parks_controller.rb
def import
SkatePark.import(params[:body])
end
模型
class SkatePark < ApplicationRecord
require 'csv'
def self.import(file)
CSV.foreach("file", headers: true) do |row|
skate_park_hash = row.to_hash
skate_park = SkatePark.where(name: skate_park_hash["name"])
if skate_park.count == 1
skate_park.first.update_attributes(skate_park_hash)
else
SkatePark.create!(skate_park_hash)
end
end
end
end
错误
Started POST "/skate_parks/import" for ::1 at 2016-05-26 13:48:34 +1000
Processing by SkateParksController#import as HTML
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms)
Errno::ENOENT (No such file or directory @ rb_sysopen - file):
app/models/skate_park.rb:6:in `import'
app/controllers/skate_parks_controller.rb:7:in `import'
答案 0 :(得分:2)
问题是params[:body]
是nil
,因此您实际上是在调用SkatePark.import(nil)
。 Rails没有将原始POST主体放入params
,就像你显然认为的那样。
您有两种选择。在我看来,更好的选择是将数据上传为multipart/form-data
。当用户在<input type="file">
中选择文件时,您将执行与浏览器相同的操作,而不是将原始数据放入POST主体,也就是说您将其编码为表单数据。执行此操作后,您将能够通过params
访问数据,如“上传文件”下的Form Helpers Rails Guide中所述。 (由于您显然没有使用表单,因此可以跳到“上传的内容”以了解如何处理您收到的数据。)
要使用Postman对此进行测试,请按照Sending Requests文档中“请求正文”下的“表单数据”说明进行操作,我将在此处摘录以供后人使用:
multipart / form-data是Web表单用于传输数据的默认编码。这模拟在网站上填写表格并提交。表单数据编辑器允许您为数据设置键/值对(使用key-value editor)。您也可以将文件附加到密钥。
您的另一个选择是直接通过request.raw_post
访问POST正文,如下所述:How to access the raw unaltered http POST data in Rails?这不是非常“Railsy”,但是,其他事情将更难以测试。