ファイルをダウンロードするのに使われるRailsのメソッドには「 send_file 」と「 send_data 」があります。
ファイルをダウンロードする。
サーバー側に保存されているファイルを送るのなら「 send_file 」を使うべきかもしれません。
この二つのメソッドの違いについてはstack overflowで回答されています。簡単に説明します。
send_file(path, options = {})send_data(data, options = {})
このように与える引数がファイルのパスであるのが「 send_file 」で、「 send_data 」にはデータを与えます。
例えばこんな感じです。こちら(api.rubyonrails.org)も参考にしました。
file_path = File.join(Rails.root, 'files', 'example.pdf')
send_file(file_path, filename: 'example.pdf')
data = 'こんにちは, Rails !'
send_data(data, filename: 'my_file.txt')
# こんな使い方もできるそうだ。
send_data generate_tgz('dir'), filename: 'dir.tgz'(ちなみに、 generate_tgz というメソッドはありません。自分で実装します。)
日本語ファイル名
ファイルをダウンロードするときに気になるのが日本語のファイル名が文字化けしないか?ということだと思います。 「 send_file 」や「 send_data 」が送る相手はブラウザですので、文字化けするしないはブラウザの対応状況によります。 文字化けしてしまう時にはファイル名をURLエンコードする必要があります。
URLエンコードするメソッドに次のものがありました。
ERB::Util.url_encode(ファイル名)URI.encode(ファイル名)ちなみにこちらにはURI.decode('デコードしたい文字列')もあります。
URLエンコードする必要があるブラウザ
多くの方がIEで文字化けする、というように書かれていましたが、 私が試した結果では、IEもChromeもFirefoxもすべて文字化けてしまいました。本当のところはどうなんでしょう。 また、URLエンコードするとIEとChromeは正しいファイル名でダウンロードしてくれましたが、Firefoxでは日本語部分を空白(あるいは空文字)にされてしまいました。
下記のコードはIEとChromeの時にURLエンコードをするようにしたものです。 ブラウザの判定は、ヘッダの USER_AGENT に「MSIE」か「Trident」が含まれていたら(IEのバージョンにより異なる)IEなのでURLエンコードの対象となり、 また「Chrome」が含まれていたらChromeなのでURLエンコードを行います(Firefoxは?… 今のところ対処法なし)。
View
ファイルをダウンロードするコントローラメソッドへのリンクを作ります。
<%= link_to material.name, file_download_path(material) %>(ここでのmaterialは、ダウンロードさせたいファイルの情報を持ったモデルです)
Controller
if File.exist?(material.file_path)
if require_encode_browser?
file_name = ERB::Util.url_encode(material.name)
else
file_name = material.name
end
path = File.join(Rails.root, material.file_path)
send_file(
path,
filename: file_name,
type: 'application/octet-stream', # デフォルト
disposition: 'attachment' # デフォルト
)
end
def require_encode_browser?
(/MSIE/ =~ request.user_agent) || (/Trident/ =~ request.user_agent) || (/Chrome/ =~ request.user_agent)
end