0
0

More than 1 year has passed since last update.

【Active Storage】ストレージ内にzipファイルを生成してDLする機能作成までにやったこと

Posted at

このノートの内容

  • クラウドストレージ内のファイルをzipにまとめてDLしたかった
  • ファイル処理のメソッドの理解が曖昧だったので、基礎から調べながら行った

使用Gem

調べた内容

File.join

連結したいディレクトリ名やファイル名を文字列(もしくは文字列を要素に持つ配列)で与えます。

File.join("a","b")                        # => "a/b"

File.open

Fileクラスから提供されているopenメソッドで、Rubyでファイルを開いたり・作成したりする際に呼び出す処理です。

読み込みや書き込み時にもファイルを開く必要があるため、ファイル関連処理の起点とも言えます。

インスタンス = File.open(ファイルパス, 読み書きモード)

ファイルパス以外はオプションでの指定となります。
読み書きモードには'w','r'などがありますが、バイナリを扱うものは'wb'などbがつきます。

Zip::File.open

Zipモジュール下ののFile.open。

Zip::File.open("my.zip", create: true)

上記の例では、zipアーカイブを開きmy.zip(存在しない場合は作成します)内に処理を行います。("my.zip"に入るのはパスです。)

FileUtils.mkdir_p

例えば、

FileUtils.mkdir_p('/usr/local/lib/ruby')

は以下の全ディレクトリを (なければ) 作成します。

  • /usr
  • /usr/local
  • /usr/local/bin
  • /usr/local/bin/ruby

よく似たメソッドに FileUtils.mkdir("ディレクトリ名")がありますが、こちらは引数に指定されたディレクトリのみを作成します。

Pathname.join

与えられたパス名を連結してくれるメソッドです。

path0 = Pathname("/usr")                # Pathname:/usr
path0 = path0.join("bin/ruby")          # Pathname:/usr/bin/ruby

Pathname.joinメソッドについては、下記の記事も面白かったです。

Dir.glob

ワイルドカードの展開を行い、パターンにマッチするファイル名を文字列の配列として返します。
/sample配下にhoge.txtfuga.txtがあった時

Dir.glob("/sample/*")                      #=> ["hoge.txt", "fuga.txt"]

RubyZipについて

今回はRubyのファイル操作メソッドの他、RubyZipというgemを使いました。
READMEによると Rubyzipは、zipファイルを読み書きするためのrubyライブラリです。 とのこと

基本的な使い方

公式ページに記載のコードはこちら

require 'rubygems'
require 'zip'

folder = "Users/me/Desktop/stuff_to_zip"
input_filenames = ['image.jpg', 'description.txt', 'stats.csv']

zipfile_name = "/Users/me/Desktop/archive.zip"

Zip::File.open(zipfile_name, create: true) do |zipfile|
  input_filenames.each do |filename|
    # Two arguments:
    # - The name of the file as it will appear in the archive
    # - The original file, including the path to find it
    zipfile.add(filename, File.join(folder, filename))
  end
  zipfile.get_output_stream("myFile") { |f| f.write "myFile contains just this" }
end

OutputStream

こちらの記事によると、クラウドストレージ上でファイルをそのままzipにできるらしい。

上記記事を参考にして作成したコードがこちら。
Rubyのバージョンが記事より古く、番号指定パラメータが使用できなかったので、そこだけ書き換えました。
(あと、rakeタスクを使用しています)

some/rake/file.rake
namespace :example_task do
  desc "タスクの説明がここに入ります"
  task zip: :environment do
    tmp_dir = Rails.root.join('tmp', 'example_folder')
    FileUtils.mkdir_p(tmp_dir)
    files_to_zip =  User.find(1).images

    # zipファイル作成
    buffer = Zip::OutputStream.write_buffer do |buffer|
      files_to_zip.each do |file|
        buffer.put_next_entry(file.image.filename.to_s)
        file.image.download { |file_data| buffer.write(file_data) }
      end
    end
    
    # 作成したzipファイルをダウンロード
    File.open(Rails.root.join('tmp/example_folder','downloaded_images.zip'), 'wb') { |file|
      file.write(buffer.string)
    }
  end
end

▼番号指定パラメータに関してはこちらで勉強
https://qiita.com/jnchito/items/79f0172e60f237e2c542

結果

無事、クラウドストレージ上でzipファイルを作成し、ローカルにDLできました。
実際の運用では

  • zipにアーカイブする対象のファイルは数千ファイルあるがそれをどう処理するか
  • アーカイブしたファイルはローカルに落とすのではなく、事務の人に共有したいがどうすれば良いか

など他の課題もありましたが、そちらは一旦別の機会に。
ファイル操作について一通り学習する機会となってよかったです。

0
0
2

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
0
0