Tushar Saurabh
Tushar Saurabh

Reputation: 687

Rails - Reading uploaded text file

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

Answers (3)

Tushar Saurabh
Tushar Saurabh

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 -

is there a rails method to loop through each line of uploaded file? "each_line" is an IO method but it's not working

Thanks!!

Upvotes: 1

rohin-arka
rohin-arka

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

Lymuel
Lymuel

Reputation: 574

You should add multipart to your form just like the following

<%= form_tag '/greetings/hello', multipart: true do %>

Upvotes: 4

Related Questions