ホーム DoRuby S3から複数のファイルを取得しつつ on-the-fly でZipを作ってブラウザに返す
S3から複数のファイルを取得しつつ on-the-fly でZipを作ってブラウザに返す
 

S3から複数のファイルを取得しつつ on-the-fly でZipを作ってブラウザに返す

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

S3にダウンロードさせたいファイルが複数あるが、zipファイルでまとめて1度にダウンロードさせたいが、そんなAPIはそもそも無いので zipline という gem を使ってみました。

課題

S3にダウンロードさせたいファイルが複数あるが、zipファイルでまとめて1度にダウンロードさせたい

解決策

  • EC2インスタンスで稼働しているWebアプリケーション側でS3上の複数のファイルをまとめてzipを作成
  • zipファイルを作成するそばからクライアントへレスポンスを返す(chancked response)
    • ちょうどそんなことをやってくれる zipline という便利な gem が存在する

(タイトル画像のようなイメージ)

テスト用アプリを作る

試しに Rails アプリケーションを作ってみる

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.10.5
BuildVersion:   14F2109

$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin14]

$ rails --version
Rails 5.0.1

Railsアプリの準備

まず、準備として rails コマンドでアプリの雛形を用意

$ rails new zipline_test

上記が完了したら作成されたディレクトリに移動

$ cd zipline_test

Gemfileを編集して ‘zipline’ と ‘aws-sdk’ を追加してそれらのgemをインストール

$ echo "gem 'zipline'" >> Gemfile
$ echo "gem 'aws-sdk'" >> Gemfile
$ bundle install --path ./bundle

これでほぼ準備OK
アプリケーションを書いていく

ルートとコントローラを作る

まずURIを定義するため、config/routes.rb を以下のように編集。

Rails.application.routes.draw do
  get "download/zip"
end

次に、上記で定義したURIに対応するコントローラを定義する。
以下のコマンドでコントローラの雛形を作成。

$ rails g controller download

すると、app/controllers/download_controller.rb が作成されるので、そのファイルを以下のように編集。

class DownloadController < ApplicationController
  include ActionController::Streaming
  include Zipline

  AWS_S3_REGION = "ap-northeast-1"
  AWS_S3_BUCKET = "zipline-test"

  def zip
    zipline(s3files, "s3files.zip")
  end

  private

  # ダウンロード対象のファイルを順次zipに固めながら chunked response としてクライアントに返す
  def s3files
    s3 = Aws::S3::Client.new(region: AWS_S3_REGION)
    # ダウンロード対象のファイル
    files = %w(
      file1.json
      file2.json
      file3.json
    )
    files.lazy.map do |file|
      logger.debug "get file from s3 : #{file}"
      s3_object = s3.get_object(bucket: AWS_S3_BUCKET, key: file)
      

[s3_object.body, file]

end end end

  • AWS_S3_REGION は自分のS3バケットを作成したリージョンに
  • AWS_S3_BUCKET は自分のS3バケットの名前に
  • file1.json, file2.json, file3.json はS3バケット上のダウンロードさせたいファイル名に

サーバを起動する

あらかじめAWSに接続するためのcredential関係の環境変数(AWS_SECRET_ACCESS_KEY,AWS_ACCESS_KEY_ID)を設定してからサーバを起動する

$ export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxx
$ export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxx
$ rails s

これで http://localhost:3000/で サーバが立ち上がるはず。

URIアクセスしてみる

ブラウザで http://localhost:3000/download/zip にアクセスするとダウンロードが始まり、zipファイルがダウンロードされるはず。

参考

記事を共有

最近人気な記事