在Rails中上传文件


74

我是Rails的新手,并且正在使用CRUD技术编写RESTful网站。到目前为止,我已经创建了三个页面,所有这些页面都允许用户从数据库中创建,编辑和删除一行。但是,我的第四页需要包含一个上传文件表单,但是a)我不知道文件系统如何与Rails一起使用,因此我不知道文件应该存储在哪里。该文件约为100kb,由于会不断下载,因此无法存储在临时存储中。b)我不知道如何写文件。

如果您能告诉我如何做上面提到的事情,那就太好了-在输入表单上创建上载输入,然后将文件写入单独目录中的文件路径。

Answers:


132

更新2018

尽管下面编写的所有内容仍然适用,但Rails 5.2现在包括active_storage,它允许诸如直接上传到S3(或其他云存储服务),图像转换等之类的东西。您应该查看Rails指南并自己确定适合您的需求。


尽管有很多宝石可以很好地解决文件上传问题(有关列表,请参见https://www.ruby-toolbox.com/categories/rails_file_uploads),rails具有内置的帮助程序,可以轻松地实现自己的解决方案。

file_field在您的表单中使用-form helper,Rails会为您处理上传:

<%= form_for @person do |f| %>
  <%= f.file_field :picture %>
<% end %>

您将在控制器中访问上传的文件,如下所示:

uploaded_io = params[:person][:picture]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
  file.write(uploaded_io.read)
end

这取决于您要实现的目标的复杂性,但这对于完成简单的文件上载/下载任务是完全足够的。本示例摘自Rails指南,您可以在此处获取更多信息:http : //guides.rubyonrails.org/form_helpers.html#uploading-files


3
我不想将文件写入数据库,只是文件路径,您提供的代码不会将其写入活动记录吗?
max_

6
不,实际上代码只是将其写入文件系统,而不是写入数据库。实际上,您仍然需要以某种方式将文件与数据库记录相关联(例如,通过将上传文件的文件名设置为记录的ID)。您可以在ruby文档中查找有关的更多信息File.openruby-doc.org/core-1.9.3/File.html#method-c-open)。

7
请修改代码以wb代替来使用w,否则,对于包含非ascii字符的文件,上传可能会失败。
西罗Santilli郝海东冠状病六四事件法轮功2013年

什么是在new控制器的方法?
atw

1
@KarolSelak这个例子只是提供了一般性原则简单的文件上传,您可以了解更多有关在轨导路由和形式(guides.rubyonrails.org/routing.html / guides.rubyonrails.org/...
没法比

6

2018年9月

对于最近检查此问题的任何人,Rails 5.2+现在默认都有ActiveStorage,我强烈建议您检查一下。

由于它现在是核心Rails 5.2+的一部分,因此它具有很好的集成性并具有出色的开箱即用功能(尽管所有其他著名的宝石,如Carrierwave,Shrine,回形针等,都很棒,但是该宝石提供了非常出色的功能)我们可以在任何新的Rails项目中考虑的良好功能)

回形针团队不赞成使用Gems,而是使用Rails ActiveStorage。

这是ActiveStorage的github页面,并且到处都有大量资源

另外,我发现该视频对于了解Activestorage的功能非常有帮助


3

有一个特别适合上传文件的宝石:carrierwave。如果Wiki不能帮助您,那么RailsCast会提供很好的最佳使用方法。总而言之,fileRails表单中有一个字段类型,它会调用文件上传对话框。您可以使用它,但是“魔术”是由carrierwavegem完成的。

我不知道“如何写入文件”是什么意思,但我希望这是一个好的开始。


我知道了,所以您对这颗宝石还可以。
R Milushev

0

好的。如果您不想将文件存储在数据库中并存储在应用程序中,例如资产(自定义文件夹),则可以定义attr_accessor:document定义的非数据库实例变量,并用于form_for - f.file_field获取文件,

在控制器中

 @person = Person.new(person_params)

在这里person_params返回白名单params[:person](定义自己)

另存为

dir = "#{Rails.root}/app/assets/custom_path"
FileUtils.mkdir(dir) unless File.directory? dir
document = @person.document.document_file_name # check document uploaded params
File.copy_stream(@font.document, "#{dir}/#{document}")

注意,.gitignore如果要再次使用此文件,请在&中添加此路径asset_path,方法是:application.rb

每当表单读取文件字段时,它将存储在tmp文件夹中,以后您可以在自己的位置存储,我举了一个示例来存储在资产上

注意:像这样存储文件会增加应用程序的大小,最好使用来存储在数据库中paperclip


0

在您的Intiallizer / carrierwave.rb中

if Rails.env.development? || Rails.env.test?
    config.storage = :file
    config.root = "#{Rails.root}/public"
    if Rails.env.test?
      CarrierWave.configure do |config|
        config.storage = :file
        config.enable_processing = false
      end
    end
 end

在本地运行时使用此文件存储在文件中

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.