开发者社区> 问答> 正文

Rails应用 上传文件

已解决

展开
收起
2018-06-24 05:49:58 762 0
1 条回答
写回答
取消 提交回答
  • 采纳回答

    详细解答可以参考官方帮助文档

    与Rails集成

    在Rails应用中使用OSS Ruby SDK只需要在Gemfile中添加以下依赖:

    1. gem 'aliyun-sdk', '~> 0.3.0

    然后在使用OSS时引入依赖就可以了:

    1. require 'aliyun/oss'

    另外,SDK的rails/目录下提供一些方便用户使用的辅助代码。

    下面我们将利用SDK来实现一个简单的OSS文件管理器(oss-manager),最终包含以下功能:

    • 列出用户所有的Bucket
    • 列出Bucket下所有的文件,按目录层级列出
    • 上传文件
    • 下载文件

    1. 创建项目

    先安装Rails,然后创建一个Rails应用,oss-manager:

    1. gem install rails
    2. rails new oss-manager

    作为一个好的习惯,使用git管理项目代码:

    1. cd oss-manager
    2. git init
    3. git add .
    4. git commit -m "init project"

    2. 添加SDK依赖

    编辑oss-manager/Gemfile,向其中加入SDK的依赖:

    1. gem 'aliyun-sdk', '~> 0.3.0'

    然后在oss-manager/下执行:

    1. bundle install

    保存这一步所做的更改:

    1. git add .
    2. git commit -m "add aliyun-sdk dependency"

    3. 初始化OSS Client

    为了避免在项目中用到OSS Client的地方都要初始化,我们在项目中添加一个初始化文件,方便在项目中使用OSS Client:

    1. # oss-manager/config/initializers/aliyun_oss_init.rb
    2. require 'aliyun/oss'
    3. module OSS
    4. def self.client
    5. unless @client
    6. Aliyun::Common::Logging.set_log_file('./log/oss_sdk.log')
    7. @client = Aliyun::OSS::Client.new(
    8. endpoint:
    9. Rails.application.secrets.aliyun_oss['endpoint'],
    10. access_key_id:
    11. Rails.application.secrets.aliyun_oss['access_key_id'],
    12. access_key_secret:
    13. Rails.application.secrets.aliyun_oss['access_key_secret']
    14. )
    15. end
    16. @client
    17. end
    18. end

    上面的代码在SDK的rails/目录下可以找到。这样初始化后,在项目中使用OSSClient就非常方便:

    1. buckets = OSS.client.list_buckets

    其中endpoint和AccessKeyId/AccessKeySecret保存在oss-manager/conf/secrets.yml中,例如:

    1. development:
    2. secret_key_base: xxxx
    3. aliyun_oss:
    4. endpoint: xxxx
    5. access_key_id: aaaa
    6. access_key_secret: bbbb

    保存代码:

    1. git add .
    2. git commit -m "add aliyun-sdk initializer"

    4. 实现List buckets功能

    首先用rails生成管理Buckets的controller:

    1. rails g controller buckets index

    这样会在oss-manager中生成以下文件:

    • app/controller/buckets_controller.rb Buckets相关的逻辑代码
    • app/views/buckets/index.html.erb Buckets相关的展示代码
    • app/helpers/buckets_helper.rb 一些辅助函数

    首先编辑buckets_controller.rb,调用OSS Client,将list_buckets的结果存放在@buckets变量中:

    1. class BucketsController < ApplicationController
    2. def index
    3. @buckets = OSS.client.list_buckets
    4. end
    5. end

    然后编辑views/buckets/index.html.erb,将Bucket列表展示出来:

    1. <h1>Buckets</h1>
    2. <table class="table table-striped">
    3. <tr>
    4. <th>Name</th>
    5. <th>Location</th>
    6. <th>CreationTime</th>
    7. </tr>
    8. <% @buckets.each do |bucket| %>
    9. <tr>
    10. <td><%= link_to bucket.name, bucket_objects_path(bucket.name) %></td>
    11. <td><%= bucket.location %></td>
    12. <td><%= bucket.creation_time.localtime.to_s %></td>
    13. </tr>
    14. <% end %>
    15. </table>

    其中bucket_objects_path是一个辅助函数,在app/helpers/buckets_helper.rb中:

    1. module BucketsHelper
    2. def bucket_objects_path(bucket_name)
    3. "/buckets/#{bucket_name}/objects"
    4. end
    5. end

    这样就完成了列出所有Bucket的功能。在运行之前,我们还需要配置Rails的路由,使得我们在浏览器中输入的地址能够调用正确的逻辑。编辑config/routes.rb,增加一条:

    1. resources :buckets do
    2. resources :objects
    3. end

    好了,在oss-manager/下输入rails s以启动rails server,然后在浏览器中输入http://localhost:3000/buckets/就能看到Bucket列表了。

    最后保存一下代码:

    1. git add .
    2. git commit -m "add list buckets feature"

    5. 实现List objects功能

    首先生成一个管理Objects的controller:

    1. rails g controller objects index

    然后编辑app/controllers/objects_controller.rb:

    1. class ObjectsController < ApplicationController
    2. def index
    3. @bucket_name = params[:bucket_id]
    4. @prefix = params[:prefix]
    5. @bucket = OSS.client.get_bucket(@bucket_name)
    6. @objects = @bucket.list_objects(:prefix => @prefix, :delimiter => '/')
    7. end
    8. end

    上面的代码首先从URL的参数中获取Bucket名字,为了只按目录层级显示,我们还需要一个前缀。然后调用OSS Client的list_objects接口获取文件列表。注意,这里获取的是指定前缀下,并且以’/‘为分界的文件。这样做是为也按目录层级列出文件。请参考管理文件

    接下来编辑app/views/objects/index.html.erb:

    1. <h1>Objects in <%= @bucket_name %></h1>
    2. <p> <%= link_to 'Upload file', new_object_path(@bucket_name, @prefix) %></p>
    3. <table class="table table-striped">
    4. <tr>
    5. <th>Key</th>
    6. <th>Type</th>
    7. <th>Size</th>
    8. <th>LastModified</th>
    9. </tr>
    10. <tr>
    11. <td><%= link_to '../', with_prefix(upper_dir(@prefix)) %></td>
    12. <td>Directory</td>
    13. <td>N/A</td>
    14. <td>N/A</td>
    15. </tr>
    16. <% @objects.each do |object| %>
    17. <tr>
    18. <% if object.is_a?(Aliyun::OSS::Object) %>
    19. <td><%= link_to remove_prefix(object.key, @prefix),
    20. @bucket.object_url(object.key) %></td>
    21. <td><%= object.type %></td>
    22. <td><%= number_to_human_size(object.size) %></td>
    23. <td><%= object.last_modified.localtime.to_s %></td>
    24. <% else %>
    25. <td><%= link_to remove_prefix(object, @prefix), with_prefix(object) %></td>
    26. <td>Directory</td>
    27. <td>N/A</td>
    28. <td>N/A</td>
    29. <% end %>
    30. </tr>
    31. <% end %>
    32. </table>

    上面的代码将文件按目录结构显示,主要逻辑是:

    1. 总是在第一个显示’../‘指向上级目录
    2. 对于Common prefix,显示为目录
    3. 对于Object,显示为文件

    上面的代码中用到了with_prefix, remove_prefix等一些辅助函数,它们定义在app/helpers/objects_helper.rb中:

    1. module ObjectsHelper
    2. def with_prefix(prefix)
    3. "?prefix=#{prefix}"
    4. end
    5. def remove_prefix(key, prefix)
    6. key.sub(/^#{prefix}/, '')
    7. end
    8. def upper_dir(dir)
    9. dir.sub(/[^\/]+\/$/, '') if dir
    10. end
    11. def new_object_path(bucket_name, prefix = nil)
    12. "/buckets/#{bucket_name}/objects/new/#{with_prefix(prefix)}"
    13. end
    14. def objects_path(bucket_name, prefix = nil)
    15. "/buckets/#{bucket_name}/objects/#{with_prefix(prefix)}"
    16. end
    17. end

    完成之后运行rails s,然后在浏览器中输入地址http://localhost:3000/buckets/my-bucket/objects/就可以查看文件列表了。

    惯例保存代码:

    1. git add .
    2. git commit -m "add list objects feature"

    6. 下载文件

    注意到在上一步显示文件列表时,我们为每个文件也添加了一个链接:

    1. <td><%= link_to remove_prefix(object.key, @prefix),
    2. @bucket.object_url(object.key) %></td>

    其中Bucket#object_url是一个为文件生成临时URL的方法,参考下载文件

    7. 上传文件

    在Rails这种服务端应用中,用户上传文件有两种办法:

    1. 用户先将文件上传到Rails的服务器上,服务器再将文件上传到OSS。这样做需要Rails服务器作为中转,文件多拷贝了一遍,不是很高效。
    2. 服务器为用户生成表单和临时凭证,用户直接上传文件到OSS。

    第一种方法比较简单,与普通的上传文件一样。下面我们用的是第二种方法:

    首先在app/controllers/objects_controller.rb中增加一个#new方法,用于生成上传表单:

    1. def new
    2. @bucket_name = params[:bucket_id]
    3. @prefix = params[:prefix]
    4. @bucket = OSS.client.get_bucket(@bucket_name)
    5. @options = {
    6. :prefix => @prefix,
    7. :redirect => 'http://localhost:3000/buckets/'
    8. }
    9. end

    然后编辑app/views/objects/new.html.erb:

    1. <h2>Upload object</h2>
    2. <%= upload_form(@bucket, @options) do %>
    3. <table class="table table-striped">
    4. <tr>
    5. <td><label>Bucket:</label></td>
    6. <td><%= @bucket.name %></td>
    7. </tr>
    8. <tr>
    9. <td><label>Prefix:</label></td>
    10. <td><%= @prefix %></td>
    11. </tr>
    12. <tr>
    13. <td><label>Select file:</label></td>
    14. <td><input type="file" name="file" style="display:inline" /></td>
    15. </tr>
    16. <tr>
    17. <td colspan="2">
    18. <input type="submit" class="btn btn-default" value="Upload" />
    19. <span>&nbsp;&nbsp</span>
    20. <%= link_to 'Back', objects_path(@bucket_name, @prefix) %>
    21. </td>
    22. </tr>
    23. </table>
    24. <% end %>

    其中upload_form是SDK提供的一个方便用户生成上传表单的辅助函数,在SDK的代码rails/aliyun_oss_helper.rb中。用户需要将其拷贝到app/helpers/目录下。完成之后运行rails s,然后访问http://localhost:3000/buckets/my-bucket/objects/new就能够上传文件了。

    最后记得保存代码:

    1. git add .
    2. git commit -m "add upload object feature"

    8. 添加样式

    为了让界面更好看一些,我们可以添加一点样式(CSS)。

    首先下载bootstrap,解压后将bootstrap.min.css拷贝到app/assets/stylesheets/下。

    然后在修改app/views/layouts/application.html.erb,将yield一行改成:

    1. <div id="main">
    2. <%= yield %>
    3. </div>

    这会为每个页面添加一个id为main的<div>,然后修改app/assets/stylesheets/application.css,加入以下内容:

    1. body {
    2. text-align: center;
    3. }
    4. div#main {
    5. text-align: left;
    6. width: 1024px;
    7. margin: 0 auto;
    8. }

    这会让网页的主体内容居中显示。通过添加简单的样式,我们的页面是不是更加赏心悦目了呢?

    至此,一个简单的demo就完成了。完整的demo代码请参看 Alibaba Cloud OSS Rails Demo

    2018-06-27 16:35:29
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载