こんにちは、エンジニアのさもです
仕事でファイルをzipにまとめてダウンロードする機能を実装したので、railsでzipファイルの作り方・ダウンロードの方法をまとめます。
目次
はじめに
railsアプリでファイルのダウンロードはsend_fileかsend_dataで行えますよね。
今回はzipでまとめてからダウンロードする方法を紹介したいと思います。
使うgem
railsでzipファイルを扱う場合、rubyzipとziprubyというgemがあるのですが、
- google検索での検索結果の多さ
- 最近も修正がされていて活発
という2点からrubyzipを使いたいと思います
Gemfileにgem 'rubyzip'
と書いて、bundle installすればOKです。
実装
zipファイルの作成から送信までは以下のようになります。
zip_filename = "#{Rails.root}/upload/zip/document.zip" Zip::File.open(zip_filename, Zip::File::CREATE) do |zipfile| filenames.each_with_index do |filename, i| zipfile.get_output_stream("document#{i + 1}.txt"){|s| s.print( File.read(filename) ) } end end # 送信 send_data(File.read(zip_filename), filename: "document.zip") File.delete(zip_filename)
- filenamesはファイル名の配列です。絶対パスで書いておいてください。
send_dataとsend_fileの違い
railsでのファイル送信ではsend_fileとsend_dataがあります。
この2つの違いは以下のとおりです
- send_file
- 送信するときにファイルの実態を見る
- 引数にファイルへのパスを渡す
- send_fileした後でファイルを削除するとエラーになる
- send_data
- 送信するときにメモリにファイルを展開して、送信する
- 引数にファイルの実態を渡す
- send_data後すぐにファイルを消すことができる
私はどちらかといえば、ファイルの削除ができることから、send_dataを使うことが多いです。
日本語ファイル名の場合
zipでまとめるファイルが日本語ファイルの場合、ダウンロードすると文字化けすることがあります。(windows)
そんなときは、nkfです。
require 'nkf' zip_filename = "#{Rails.root}/upload/zip/document.zip" Zip::File.open(zip_filename, Zip::File::CREATE) do |zipfile| filenames.each_with_index do |filename, i| zipfile.get_output_stream(NKF::nkf("-s","document#{i + 1}.txt")){|s| s.print( File.read(filename) ) } end end # 送信 send_data(File.read(zip_filename), filename: "document.zip") File.delete(zip_filename)
これでwindowsでは問題なくなりましたが、macでどう見えるかは分かりません。
文字コードの問題早くなくなるといいですね。
最後に
ざっくりとですが、zipファイルでファイルをまとめてダウンロードする方法を紹介しました。
業務や趣味の開発でお役に立てれば幸いです。
読者になっていただければブログを続ける励ましになるので、よろしくお願いします。