RailsでファイルをDLさせたい
Railsでxmlやらjsonやらをアクセスされたら出力内容をそのまんまファイル保存してもらいたかったり
なんならZIPしてDLさせたかったりする(xmlではないかな)場合こうかな?と書いてみた。
viewファイルでなんとかする場合
xml
index.rss.jbuilder
xml.instruct! :xml, :version => "1.0"
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title "title"
@articles.each do |article|
xml.item do
xml.title article.title
xml.description strip_tags(article.content.gsub(/[\r\n]/,"")).truncate(400)
xml.pubDate article.created_at.to_s(:rfc822)
xml.guid "http://aaa.aa/article/#{article.id}"
xml.link "http://aaa.aa/article/#{article.id}"
end
end
end
end
json
index.json.jbuilder
json.array!(@articles) do |article|
json.id article.id
json.title article.title
json.content article.content
end
出力→DL
def dl
@articles = Article.all()
respond_to do |format|
# json
format.json do
send_data render_to_string, filename: "articles.json", type: :json
end
# xml
format.rss do
send_data render_to_string, filename: "articles.xml", type: :xml
end
end
end
出力→zip→DL
def zip_dl
require 'rubygems'
require 'zip'
require 'tmpdir'
tmpdir = Dir.mktmpdir
filename = 'data.zip'
begin
Zip::File.open("#{tmpdir}/#{filename}", Zip::File::CREATE) do |zip|
@articles = Article.all()
zip.get_output_stream("articles.xml") do |fp|
fp.puts render_to_string(:template => "articles/index.rss.builder", :layout => false)
end
zip.get_output_stream("articles.json") do |fp|
fp.puts render_to_string(:template => "articles/index.json.builder", :layout => false)
end
end
zip_data = File.read("#{tmpdir}/#{filename}")
send_data(zip_data, :type => 'application/zip', :filename => filename)
ensure
FileUtils.remove_entry_secure tmpdir
end
modelでなんとかする場合
各フォーマットへの変換関数を利用
article.rb
def self.get_json()
json = Article.all()
# belongs_toのアイテムなどをアレしてもいい
return json.to_json
end
def self.get_xml()
json = Article.all()
# belongs_toのアイテムなどをアレしてもいい
return json.to_xml
end
zip→DL
def zip_dl
require 'rubygems'
require 'zip'
require 'tmpdir'
tmpdir = Dir.mktmpdir
filename = 'data.zip'
begin
Zip::File.open("#{tmpdir}/#{filename}", Zip::File::CREATE) do |zip|
zip.get_output_stream("articles.json") do |fp|
fp.puts Article.get_json()
end
end
Zip::File.open("#{tmpdir}/#{filename}", Zip::File::CREATE) do |zip|
zip.get_output_stream("articles.xml") do |fp|
fp.puts Article.get_xml()
end
end
zip_data = File.read("#{tmpdir}/#{filename}")
send_data(zip_data, :type => 'application/zip', :filename => filename)
ensure
FileUtils.remove_entry_secure tmpdir
end
end
もっといい書き方ないかなー?