このノートの内容
- クラウドストレージ内のファイルを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.txt
とfuga.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タスクを使用しています)
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にアーカイブする対象のファイルは数千ファイルあるがそれをどう処理するか
- アーカイブしたファイルはローカルに落とすのではなく、事務の人に共有したいがどうすれば良いか
など他の課題もありましたが、そちらは一旦別の機会に。
ファイル操作について一通り学習する機会となってよかったです。