webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

railsでファイルをzip形式にまとめてダウンロードする

f:id:s-uotani-zetakansu:20170901155929j:plain

こんにちは、エンジニアのさもです

仕事でファイルを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ファイルでファイルをまとめてダウンロードする方法を紹介しました。

業務や趣味の開発でお役に立てれば幸いです。

読者になっていただければブログを続ける励ましになるので、よろしくお願いします。