Ruby on Rails - 文件上传



您可能需要一个功能,让网站访问者能够将文件上传到您的服务器。Rails 使得处理此需求非常容易。现在我们将继续进行一个简单的小型 Rails 项目。

像往常一样,让我们从一个名为 testfile 的新 Rails 应用程序开始。让我们使用简单的 rails 命令创建应用程序的基本结构。

tp> rails new testfile

在开始应用程序开发之前,我们应该安装如下所示的 gem 文件:

gem install carrierwave
gem install bootstrap-sass

打开您的 Gemfile,并在底部添加以下两个 gem,如下图所示:

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

现在打开 resume 模型并调用上传器,如下所示。Resume 模型位于 app/models/resume.rb 中:

class Resume < ActiveRecord::Base
   mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.
   validates :name, presence: true # Make sure the owner's name is present.
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 [email protected]? %>
   <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>

现在启动服务器并访问 https://127.0.0.1:3000。它将生成类似于以下屏幕的屏幕:

Output

我们需要做的最后一件事是过滤允许的文件类型列表。为此,我们需要在 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

现在启动服务器并访问 https://127.0.0.1:3000。现在输入错误的格式;它将生成错误消息,如下所示:

Output Wrong

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

广告