Ruby-on-rails 如何读取用户上传的文件,而不将其保存到数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2521053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:27:45  来源:igfitidea点击:

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

ruby-on-railsxmlruby

提问by GoodGets

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:

我希望能够读取用户上传的 XML 文件(小于 100kb),但不必先将该文件保存到数据库中。我不需要该文件超过当前操作(它的内容被解析并添加到数据库中;但是,解析文件不是问题)。由于可以使用以下方式读取本地文件:

File.read("export.opml")

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

我想只为:uploaded_file 创建一个file_field,然后尝试用

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.

但所做的只是抛出一个 TypeError(不能将 HashWithIndifferentAccess 转换为 String)。我真的尝试了很多不同的东西(包括从 /tmp 目录中读取),但没有一个能正常工作。

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?

我设置了一个自定义操作(上传)来处理 file_field 上传,提交后,它被传递给另一个自定义操作(解析)进行处理。这可能是我问题的一部分吗?

回答by vladr

You are very close. Check the class typeof params[:uploaded_file], it should typically be either a StringIOor a Tempfileobject -- both of which already act as files, and can be read using their respective readmethod(s).

你很亲近。检查类型params[:uploaded_file],它通常应该是AStringIOTempfile对象-这两者已经作为文件,并且可以使用它们各自的读出read方法(一个或多个)。

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:

可以肯定的是( 的类类型params[:uploaded_file]可能会因您使用的是 Mongrel、Passenger、Webrick 等而有所不同),您可以进行更详尽的尝试:

# 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_nameand methodparameters when invoking file_fieldin your view, or that your server is not giving you a hash with keys like :content_typeetc. (in which case please comment on this post with the Bad file_data ...output from development.log/production.log.)

如果在您的情况下,结果证明这params[:uploaded_file]是一个散列,请确保在您的视图中调用时没有错误地翻转object_namemethod参数file_field,或者您的服务器没有给您一个带有诸如:content_type等键的散列(在这种情况下请使用/的Bad file_data ...输出评论这篇文章。)development.logproduction.log

回答by Ivan

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

我需要阅读 yaml 文件。我使用 remotipart 和这里的代码:

in html.slim

在 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)