Reputation: 687
I am referring to the stackoverflow post https://stackoverflow.com/a/2521135/2607331
to understand how to read files.
View -
<%= form_tag ('/greetings/hello') do %>
<label for="file">File to Upload</label> <%= file_field_tag "file" %>
<div><%= submit_tag 'Process' %></div>
<% end %>
Routes -
Rails.application.routes.draw do
post 'greetings/hello'
controller -
class GreetingsController < ApplicationController
def hello
@filename = params[:file]
if @filename.respond_to?(:read)
@lines = file_data.read
elsif @filename.respond_to?(:path)
@lines = File.read(file_data.path)
else
logger.error "Bad file_data: #{@filename.class.name}: #
{@filename.inspect}"
end
render "hello"
end
end
As per the post, the params[:file] would be a tempfile or StringIO object, however in my case it is string. Not sure what is going wrong. Below is the logger output.
Started POST "/greetings/hello" for 183.83.51.8 at 2016-05-03 03:45:40 +0000
Cannot render console from 183.83.51.8! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by GreetingsController#hello as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0r0Ny6rqlv9Gts1PBh+J4Dk7B+9WPea3HK1cgR/dWTLFrkXW+eggX+tie4wFs+F4lHM5RGpAHXL6EO3sKjd0sw==", "file"=>"sitcomquery.txt", "commit"=>"Process"}
Bad file_data: String: "sitcomquery.txt"
Rendered greetings/hello.html.erb within layouts/application (5.6ms)
Completed 500 Internal Server Error in 97ms (ActiveRecord: 0.0ms)
EDIT
Changed index.html.erb to include multipart -
<%= form_tag '/greetings/hello' ,multipart: true do %>
<label for="file">File to Upload</label> <%= file_field_tag "file" %>
<div><%= submit_tag 'Process' %></div>
<% end %>
In controller, I am able to read it with -
tempfl = params[:file]
@lines = tempfl.read
However, @lines is a big string. I need to read it in such a way that @lines is array of lines. However readlines is not a method of ActionDispatch::Http::UploadedFile object. Do i need to save the file and perform readlines, or is there anyway I can read each line without saving file.
Upvotes: 4
Views: 4832
Reputation: 687
The issue was to read each lines of uploaded file and spit it out line by line. Normal readlines or each_line method doesnt work as the Uploaded file is of class "UploadedFile" and doesnt support IO methods. The solution can be found in another stackoverflow post -
Thanks!!
Upvotes: 1
Reputation: 799
class GreetingsController < ApplicationController
def hello
@filename = params[:file]
if @filename.respond_to?(:read)
@lines = file_data.read
elsif @filename.respond_to?(:path)
@lines = File.read(file_data.path)
else
logger.error "Bad file_data: #{@filename.class.name}: #
{@filename.inspect}"
end
render "hello"
end
end
In this code @filename
contains a string and you have checked string contains method read or not by boolean function respond_to? and it always gonna return false because string do not have method read. there are lots of option to check file below is one of them.
file = File.file?(params[:file])
if file
@lines = File.read(params[:file])
else
"your message"
end
OR if you want to read params file as IO object you need to add multipart in form
<%= form_for(<object>, url: <path>, method: :post, remote: :true, html: {
multipart: true, }) do |f| %>
<input type="file" name="file_batch_upload" />
<% end %>
For more details
https://stackoverflow.com/a/36765124/5715918
Upvotes: 2
Reputation: 574
You should add multipart to your form just like the following
<%= form_tag '/greetings/hello', multipart: true do %>
Upvotes: 4