Difficulty with send_data in Ruby on Rails in conjunction with Spreadsheet plug-in

Chris K picture Chris K · Oct 18, 2010 · Viewed 8.2k times · Source

I have a function in a controller that takes in some specifications and generates a report on them. This function user_report is called in a view:

< %= submit_to_remote 'submit-button', "Export Report to Excel", :url => { :controller => :reports, :action => :user_report, :print_state => 'print'} % >

In reports_controller I use the Spreadsheet plugin to generate an Excel file within the user_report function. I want to use send_data to stream the file to the user without creating it on the server first. The research I've done shows that using StringIO is the way to go, as shown below. Frustratingly, nothing happens when I call send_data. The plugin seems to work well creating a file and saving it on the server, but does nothing when I use send_file, suggesting that the problem doesn't lie in the plugin. But then what am I doing wrong with send_file/send_data?

The function itself looks like this:

def user_report

if request.post?
  unless params[:reports][:userid].blank?
    @userid=params[:reports][:userid]
  end
  if params[:print_state]=='print'  

    report = Spreadsheet::Workbook.new
    info = report.create_worksheet :name => 'User Information'
    info.row(1).push 'User ID', @userid

    @outfile = "Report_for_#{@userid}.xls"

    require 'stringio'
    data = StringIO.new ''
    report.write data
    send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => @outfile
  end

  respond_to do |format|
    format.js { }
  end
end

end

The log file reads 2010-10-18 14:13:59 INFO -- Sending data Report_for_jjohnson.xls but no download begins in-browser. I've succeed in using send_data on this app before, which is confusing.

I'm using Rails v2.3, Ruby v1.8.7, and Spreadsheet v6.4.1 at spreadsheet.rubyforge.org.

Answer

Asang Dani picture Asang Dani · Oct 23, 2010

Just change the line:

send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => @outfile

to:

send_data data.string.bytes.to_a.pack("C*"), :type=>"application/excel", :disposition=>'attachment', :filename => @outfile