rails http response to Donwload excel file - ruby-on-rails

i saw this code in github
require "csv"
csv_str = CSV.generate do |csv|
csv << ["awesome", "csv"]
end
result = IO.popen("secure-spreadsheet --password secret", "r+") do |io|
io.write(csv_str)
io.close_write
io.read
end
File.open("output.xlsx", "w") { |f| f.write(result) }
this code store a Excel file(output.xlsx) in my project file.
how can i convert this "store file scenario" in to "download the file in the browser"?

In your config/initializers/mime_types.rb register the xlsx mime_type(It is not available in Rails by default) :
Mime::Type.register "application/xlsx", :xlsx
Assuming your code that does the excel generation works and is in a controller method(private) named excel_file (I think its better to extract to a service/lib class):
def excel_file
csv_str = CSV.generate do |csv|
csv << ["awesome", "csv"]
end
IO.popen("secure-spreadsheet --password secret", "r+") do |io|
io.write(csv_str)
io.close_write
io.read
end
end
In your controller action you should be able to do something like this
def download_excel
respond_to do |format|
format.xlsx { send_data excel_file, type: 'application/xlsx; header=present', disposition: "attachment", filename: "output.xlsx" }
end
end
( ActionController#send_data "sends the given binary data to the browser". Read more via that link)
If you have a view, you can have a download link
<%= link_to "Download", your_download_path(format: "xlsx") %>
Users should be able to download the excel file via the link

Related

How to create a file on users machine instead of creating in server and then to download using rails

I am working on to allow download an excel file with the below code:
login = Etc.getlogin
#dataFile = "C:/rails/#{login}data.csv"
csv1=CSV.open(#dataFile, 'w') do |csv|
$data.each do |eachrow|
csv << [eachrow.name+"#gmail.com"]
end
end
send_file(#dataFile, :filename => "#{login}data", :type => "application/csv")
Using the above code, I am able to create a file and write the data.
Instead of this, how do i write the data in csv and get downloaded into users machine instead of saving in local/server.
What you can do is generate a string with the CSV library, using CSV::generate instead of CSV::open.
Controller:
class DataController < ApplicationController
def download
respond_to do |format|
format.csv { send_csv_download }
end
end
private
def send_csv_download
string = CSV.generate do |csv|
#data.each { |row| csv << ["#{row.name}#gmail.com"] }
end
send_data string, filename: 'foo.csv', type: :csv
end
end
config/routes.rb:
get '/download', to: 'data#download'
View:
<%= link_to 'Download CSV', download_path(format: :csv) %>
Note: Obviously, I have no idea where you get your #data from, since it isn't specified in your question.

Rails - Export CSV not working as expected (undefined method)

I am doing a CSV Export in Rails App.
The data is returned as a JSON array from the backend API.
But now I am getting error as "undefined method 'to_csv' for #Hash:0x007f149a5ff978" in the export_data method.
I have included require "csv" in the config/application.rb file, and did server restarts.
Not sure what I am doing wrong.
index.html.erb
<button class="btn btn-default">Export to CSV</button>
usage_controller(front end)
def export_data
rest_resource = RestClient::Resource.new( ENV['USAGE_METRICS_API'] + '/get_events_data', :verify_ssl => false )
request = rest_resource.get :Authorization => cookies.signed[:remember_token], :content_type => 'application/json'
#events_data = JSON.parse(request)
respond_to do |format|
format.html
format.csv { send_data #events_data.to_csv }
end
end
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |event|
csv << event.attributes.values_at(*column_names)
end
end
end
Your self.to_csv method doesn't make sense in the controller
You need to move to_csv to you model which will serialize the data into a csv
follow this tutorial to implement this: http://railscasts.com/episodes/362-exporting-csv-and-excel

Set character encoding when generating CSV file Rails 4.2

I have a module to generate csv file of the model when included.
# app/models/concerns/csv_exportable.rb
module CsvExportable
extend ActiveSupport::Concern
included do
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |thismodel|
csv << thismodel.attributes.values_at(*column_names)
end
end
end
end
end
and I include the module in models for which I want to generate csv file
# app/models/product.rb
class Reason < ActiveRecord::Base
include CsvExportable
.
.
end
In my controller I do
respond_to do |format|
format.html
format.csv { send_data #products.to_csv, filename: 'products.csv' }
end
I want to set the character encoding of generated csv file to Shift_JIS instead of default utf-8. What is the best way to do this ? Thank you
EDIT:
I tried
format.csv { send_data (#products.to_csv).encode("SHIFT-JIS"), filename: 'products.csv' }
now I am getting an error Encoding::ConverterNotFoundError code converter not found (UTF-8 to SHIFT-JIS)
format.csv {
send_data (#products.to_csv).encode(Encoding::SJIS),
filename: 'products.csv',
type: 'text/csv; charset=shift_jis'
}
Did the trick
You can pass encoding: '<non utf-8 encoding>' option in the options hash you passed to to_csv in CsvExportable so that it will be available for CSV.generate method while generating csv file.

Zip Excel sheet generated through gem axlsx rails

I'm facing an issue of how to zip the excel sheet generated through gem 'axlsx_rails'. For example:
class SampleController < ApplicationController::Base
def export
if params[:zip]
xxxx
else
render xlsx: 'export', filename: filename, disposition: 'attachment'
end
end
end
In the above example, right now the end user is able to download the excel sheet but if the end user requests a zip file of excel sheet, how can we do that. Because of code in 'else' block the end user is able to download the excel sheet. What I have to do if the user wants the excelsheet to be zipped before download. If you need any further info, plz let me know. Thanks
This is untested code, but try using Zip::ZipOutputStream:
def export
if params[:zip]
compressed_filestream = Zip::ZipOutputStream.write_buffer do |zos|
content = render_to_string xlsx: 'export', filename: filename
zos.put_next_entry(filename)
zos.print content
end
compressed_filestream.rewind
send_data compressed_filestream.read, filename: 'export.zip', type: 'application/zip'
else
render xlsx: 'export', filename: filename, disposition: 'attachment'
end
end
If it doesn't work, create an issue on Github, and after we get it working we can add it to the documentation.

How to export a HTML file in Rails?

I am trying to export links that are in my database into a HTML Netscape Bookmark File using Markio.
This following Ruby code is from Markio. I'm not sure how to get it to work with Rails so I can export links from my database to a file the user can download.
builder = Markio::Builder.new
builder.bookmarks << Markio::Bookmark.create({
:title => "Google",
:href => "http://google.com"
})
file_contents = builder.build_string
File.open('/path/to/bookmarks.html', 'w') { |f| f.write file_contents }
This is what I have so far in my Rails app. I am most likely going about it completely wrong because I only know how to do it with CSV and Excel. Each Link in my Rails database has a title and a url.
If I navigate to links/export in my browser it should download a file but I get the error "uninitialized constant Markio::Link".
This is my Links controller:
def export
#links = Link.all
respond_to do |format|
format.html { send_data #links.to_csv }
end
end
This is my Links model:
def self.to_csv(options = {})
builder = Markio::Builder.new
builder.bookmarks << Markio::Link.create({
:title => title,
:href => url
})
file_contents = builder.build_string
File.open('/path/to/bookmarks.html', 'w') { |f| f.write
file_contents }
end
Shouldn't Markio::Link be Markio::Bookmark? I don't see a Link object in their API.

Resources