Sending Files or Data Streams to the BrowserProblemYou want to send e-book contents directly from your database to the browser as text and give the user the option to download a compressed version of each book. SolutionYou have a table that stores plain text e-books: db/schema.rb: ActiveRecord::Schema.define(:version => 3) do create_table "ebooks", :force => true do |t| t.column "title", :string t.column "text", :text end end In the Document Controller, define a view that calls send_data if the :download parameter is present, and render if it is not: app/controllers/document_controller.rb:
require 'zlib'
require 'stringio'
class DocumentController < ApplicationController
def view
@document = Ebook.find(params[:id])
if (params[:download])
send_data compress(@document.text),
:content_type => "application/x-gzip",
:filename => @document.title.gsub(' ','_') + ".gz"
else
render :text => @document.text
end
end
protected
def compress(text)
gz = Zlib::GzipWriter.new(out = StringIO.new)
gz.write(text)
gz.close
return out.string
end
end
DiscussionIf the view action of the Document Controller is invoked with the URL http://railsurl.com/document/view/1, the e-book with an ID of 1 is rendered to the browser as plain text. Adding the download parameter to the URL, which yields http://railsurl.com/document/view/1?download=1, requests that the contents of the e-book be compressed and sent to the browser as a binary file. The browser should download it, rather than trying to render it. There are several different ways to render output in Rails. The most common are action renderers that process ERb templates, but it's also customary to send binary image data to the browser. See Also |