LoginSignup
28
22

More than 5 years have passed since last update.

Railsで大量の写真をZIPにまとめてダウンロードする

Last updated at Posted at 2017-04-16

はじめに

写真を大量にアップロードするWebサービスを作っていると、アップロードされた写真をまとめてダウンロードさせたくなることがあります。
そこで、zipline + carrierwave を使うと非常に簡単に写真をZIPにまとめてダウンロードすることができたのでご紹介します。

今回の環境

Ruby on Rails 5.0
carrierwave (1.0.0)
fog (1.38.0)
zipline (0.0.12)

今回利用したgemはこちら

fringd/zipline: A gem that lets you stream a zip file from rails
https://github.com/fringd/zipline

前提条件

写真のアップロードにはcarrierwaveを使っています。
またアップロードされた写真はfogを使ってS3に保存しています。
この形式はRailsではよく使われる方法なので実装方法は割愛します。

ルーティング

本の画像をZIPで一括ダウンロードする様にしたいので、ルーティングは下記の様にします。

#config/routes.rb
Rails.application.routes.draw do
  resources :books, only: %i(index)
end

これで /books でアクセスすると本の一覧を表示して、 /books.zip でアクセスすると本の画像をZIPでダウンロードできるようにします。

実装方法

まずはgemを追加して bundle install します。

gem 'carrierwave'
gem 'fog'
gem 'zipline'

本の一覧を表示するコードは今回の内容とは関係ないので省略しますが、ZIPで一括ダウンロードするリンクは下記の様にします。

#app/views/books/index.html.haml
= link_to 'ZIPでダウンロード', books_path(format: :zip)

Bookモデルにはimageという画像を保存するカラムを追加します。

#app/models/book.rb
class Book < ApplicationRecord
  mount_uploader :image, ImageUploader
end

後はコントローラーにZIPでダウンロードするコードを記載します。

#app/controllers/books_controller.rb
class BooksController < ApplicationController
  include ActionController::Streaming
  include Zipline

  def index
    @books = Book.all
    respond_to do |format|
      format.html
      format.zip do
        files =  @books.where.not(image: nil).map{ |book| [book.image, "#{book.id}.jpg"] }
        zipline(files, 'books.zip')
      end
    end
  end
end

files 変数にZIPにまとめたい画像ファイルを配列で入れています。
入っている配列は下記の様になっています。
ziplineがcarrierwaveに対応しているのでcarrierwaveのカラムを直接渡してあげるだけでremote_urlが画像のパスとしてセットされます。

#files変数の中身
[
  ['https://example.s3-ap-northeast-1.amazonaws.com/uploads/book/image/1/image.jpg', '1.jpg']
  ['https://example.s3-ap-northeast-1.amazonaws.com/uploads/book/image/2/image.jpg', '2.jpg']
  ['https://example.s3-ap-northeast-1.amazonaws.com/uploads/book/image/3/image.jpg', '3.jpg']
]

注意点

コントローラーの中で @books.where.not(image: nil) としてimageが無いbookは渡さない様にしています。
imageが空のカラムを渡してもエラーにはならずZIPダウンロードまで行えますが、ダウンロードしたZIPを解凍しようとすると不正なファイルとして解凍できないので注意が必要です。

まとめ

zipline + carrierwaveでとてもシンプルに一括ダウンロードが実装できました。
また、ziplineは Streaming でダウンロードしているので大きなファイルサイズのZIPであっても快適にダウンロードが行えるようになっています。

28
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
22