阿里雲團隊努力不懈,力求將最新的技術內容更快地以您最熟悉的語言呈現。本文由簡體中文內容自動轉碼而成,過程無人工干預。阿里雲不保證此自動轉碼的準確性、完整性及時效性。因轉碼造成的任何內容錯誤及因此可能帶來的損失,阿里雲概不負責,敬請見諒。本文内容請以簡體中文版本為準。
全部產品
Search
文件中心

Rails應用

更新時間: Oct 30, 2018

在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