Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to read a User uploaded file, without saving it to the database

I'd like to be able to read an XML file uploaded by the user (less than 100kb), but not have to first save that file to the database. I don't need that file past the current action (its contents get parsed and added to the database; however, parsing the file is not the problem). Since local files can be read with:

File.read("export.opml")

I thought about just creating a file_field for :uploaded_file, then trying to read it with

File.read(params[:uploaded_file])

but all that does is throw a TypeError (can't convert HashWithIndifferentAccess into String). I really have tried a lot of various things (including reading from the /tmp directory as well), but could get none of them to work.

I hope the brevity of my question doesn't mask the effort I've given to try to solve this on my own, but I didn't want to pollute this question with a hundred ways of how NOT to get it done. Big thanks to anyone who chimes in.

Here is my view:

<% form_for(:uploaded_file, @feed, :url => {:action=>'parse'}, :html=> {:multipart=>true}) do |f| %>  <p>
    <%= f.label :uploaded_file, 'Upload your file.' %><br />
    <%= f.file_field :uploaded_file %>
  </p>
  <p><%= f.submit 'upload' %></p>
<% end %>

I set up a custom action (upload) which handles the file_field upload, which after submission, is passed off to another custom action (parse) for processing. Could this be a part of my problem?

like image 249
GoodGets Avatar asked Mar 26 '10 03:03

GoodGets


2 Answers

You are very close. Check the class type of params[:uploaded_file], it should typically be either a StringIO or a Tempfile object -- both of which already act as files, and can be read using their respective read method(s).

Just to be sure (the class type of params[:uploaded_file] may vary depending on whether you are using Mongrel, Passenger, Webrick etc.) you can do a slightly more exhaustive attempt:

# Note: use form validation to ensure that
#  params[:uploaded_file] is not null

file_data = params[:uploaded_file]
if file_data.respond_to?(:read)
  xml_contents = file_data.read
elsif file_data.respond_to?(:path)
  xml_contents = File.read(file_data.path)
else
  logger.error "Bad file_data: #{file_data.class.name}: #{file_data.inspect}"
end

If, in your case, it turns out that params[:uploaded_file] is a hash, make sure that you have not mistakingly flipped the object_name and method parameters when invoking file_field in your view, or that your server is not giving you a hash with keys like :content_type etc. (in which case please comment on this post with the Bad file_data ... output from development.log/production.log.)

like image 124
vladr Avatar answered Nov 11 '22 03:11

vladr


I need to read yaml files. I use remotipart and here the code:

in html.slim

 =form_tag('/locations/check_for_import', method: :post, remote: true, multipart: true)

...

<input id="uploadInput" type="file" name="uploadInput">

in controller

content = File.read(params[:uploadInput].tempfile)
doc = YAML.load(content)
like image 8
Ivan Avatar answered Nov 11 '22 05:11

Ivan