この記事はアピリッツの技術ブログ「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ファイルがダウンロードされるはず。