Ruby on Rails - 文件上传
您可能有一项要求,即希望网站访问者将文件上传到您的服务器。Rails 可以非常轻松地处理此要求。现在我们将继续一个简单而小型的 Rails 项目。
像往常一样,让我们从一个名为 testfile 的新 Rails 应用程序开始。让我们使用简单的 rails 命令创建应用程序的基本结构。
tp> rails new testfile
在开始应用程序开发之前,我们应该安装 gem 文件,如下所示 −
gem install carrierwave gem install bootstrap-sass
打开你的 gemfile 并在底部添加以下两个 gem,如下图所示 −

在 gem 文件中添加 gem 后,我们需要在控制台上运行以下命令 −
bundle install
创建模型
我们需要创建一个包含两个字符串的模型,分别为 name 和 attachment,如下所示 −
rails g model Resume name:string attachment:string
我们需要创建数据库迁移,如下所示 −
rake db:migrate
我们需要生成控制器,如下所示 −
rails g controller Resumes index new create destroy
太棒了!现在我们已经设置了基本结构。现在我们需要创建一个上传器。上传器来自 carrierwave gem,它告诉 carrierwave 如何处理文件。简而言之,它包含所有文件处理功能。运行命令创建上传器,如下所示
rails g uploader attachment
现在打开简历模型并调用上传器,如下所示。简历模型已放置在 app/models/resume.rb −
class Resume < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader # 告诉 rails 将此上传器用于此模型。
validates :name, presence: true # 确保所有者的姓名存在。
end
在控制器上工作之前,我们需要修改我们的 config/routes.db,如下所示 −
CarrierWaveExample::Application.routes.draw do
resources :resumes, only: [:index, :new, :create, :destroy]
root "resumes#index"
end
让我们编辑控制器,如下所示。
class ResumesController < ApplicationController
def index
@resumes = Resume.all
end
def new
@resume = Resume.new
end
def create
@resume = Resume.new(resume_params)
if @resume.save
redirect_to resumes_path, notice: "The resume #{@resume.name} has been uploaded."
else
render "new"
end
end
def destroy
@resume = Resume.find(params[:id])
@resume.destroy
redirect_to resumes_path, notice: "The resume #{@resume.name} has been deleted."
end
private
def resume_params
params.require(:resume).permit(:name, :attachment)
end
end
让我们在 css 文件中添加 bootstrap 实现。css 文件可以在 app/assets/stylesheets/resumes.css.scss 中
@import "bootstrap";
现在打开 app/views/layouts/application.html.erb 并添加如下所示的代码 −
<!DOCTYPE html>
<html>
<head>
<title>Tutorialspoint</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<div class = "container" style = "padding-top:20px;">
<%= yield %>
</div>
</body>
</html>
现在我们需要设置索引视图,如下所示 −
<% if !flash[:notice].blank? %>
<div class = "alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Resume", new_resume_path, class: "btn btn-primary" %>
<br />
<br />
<table class = "table table-bordered table-striped">
<thead>.
<tr>
<th>Name</th>
<th>Download Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% @resumes.each do |resume| %>
<tr>
<td><%= resume.name %></td>
<td><%= link_to "Download Resume", resume.attachment_url %></td>
<td><%= button_to "Delete", resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{resume.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
现在,让我们编辑 new.html.erb 并添加表单代码。
<% if !@resume.errors.empty? %>
<div class = "alert alert-error">
<ul>
<% @resume.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "well">
<%= form_for @resume, html: { multipart: true } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</div>
现在启动服务器并访问 http://localhost:3000。它将生成类似于以下的屏幕 −

我们需要做的最后一件事是过滤允许的文件类型列表。为此,我们需要在 app/uploaders/attachment_uploader.rb 中添加如下所示的简单代码
class AttachmentUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(pdf doc htm html docx)
end
end
现在启动服务器并访问 http://localhost:3000。现在输入错误的格式;它将生成错误消息,如下所示 −

有关 File 对象的完整详细信息,您需要阅读 Ruby 参考手册。