I am trying to send an html erb form to a user's computer as an html file. In my view, I have two buttons: "text" and "html." I have succeeded in sending a plaintext file to the user's computer when they click the "text" button, but when they click the "html" button, it just renders the erb form as if it were a view. Here is the relevant part of my controller:
def download
#notecard = Notecard.find(params[:notecard_id])
file_title = #notecard.title.downcase.tr(" ", "_")
respond_to do |format|
format.html do
response.headers['Content-Type'] = 'text/html'
response.headers['Content-Disposition'] = "attachment; filename=#{file_title}.html"
render :template => "notecards/download"
end
format.text do
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = "attachment; filename=#{file_title}.txt"
render :template => "notecards/download"
end
end
end
I've tried several other methods of handling the logic inside the "format.html do" block, including:
send_data(content, filename: 'file.html', type: 'text/plain', disposition: 'attachment')
and:
render :template => "notecards/download", filename: 'file.html', type: 'text/html', disposition: 'attachment'
Here is the code for the button in the view:
= link_to "html", notecard_download_path(notecard_id: #notecard.id, format: "html")
I've also tried changing the content type to 'text/plain' to trick it into sending the file, based on advice I received elsewhere, but that didn't work either.
You should be able to render_to_string which will download the rendered file instead of the template itself.
Change this:
format.html do
response.headers['Content-Type'] = 'text/html'
response.headers['Content-Disposition'] = "attachment; filename=#{file_title}.html"
render :template => "notecards/download"
end
To this:
format.html do
# response.headers['Content-Type'] = 'text/html'
# response.headers['Content-Disposition'] = "attachment; filename=#{file_title}.html"
# render_to_string
send_data render_to_string, filename: 'file.html', type: 'application/html', disposition: 'attachment', layout: false}
end
Related
If I render html page, I can get its content and use it to create PDF, like so:
content = params[:html]
But what if I don't want to display the HTML of the PDF I'm exporting? I tried different variations of this:
content = render_to_string(
partial: 'some_partial.html.erb', locals: #some_var
)
respond_to do |format|
format.pdf do
render pdf: 'some_pdf', locals: { content: content },
template: 'some_template.pdf.erb',
disable_javascript: true
end
end
But I just get errors, which leads me to believe that I'm coping this the wrong way...
What you could is
Create a file with a unique name -
unique_filename = Rails.root.join('public/', "#{SecureRandom.urlsafe_base64}.pdf").to_s
Use render_to_string to create the PDF -
pdf_file = render_to_string :pdf => unique_filename,
:template => 'some_template.pdf.erb',
:save_to_file => '#{unique_filename}'
:save_only => true
Save it to the file
File.open(unique_filename, 'wb') do |file|
file << pdf_file
end
I'm trying to use wicked pdf to render a html page as pdf.
mime_types.rb
Mime::Type.register "application/pdf", :pdf
controller method
def invoice
respond_to do |format|
format.html
format.pdf do
render pdf: "invoice"
end
end
end
wicked_pdf.rb
:exe_path => '/usr/local/bin/wkhtmltopdf'
invoice.pdf.erb
<div id="test_pdf">
test data
</div>
I have added the above codes and added the following gems to my project.
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
When I try to render the page, i get Template is missing error. If i rename invoice.pdf.erb to invoice.html.erb i can bypass the error, but i will be getting a html page instead of pdf.
Do I miss something?
As mentioned in the document of wicked_pdf, you can use it like this. Its self explanatory. Don't forget to create "pdfs" directory
# or from your controller, using views & templates and all wicked_pdf options as normal
pdf = render_to_string pdf: "some_file_name", template: "templates/pdf.html.erb", encoding: "UTF-8"
# then save to a file
save_path = Rails.root.join('pdfs','filename.pdf')
File.open(save_path, 'wb') do |file|
file << pdf
end
send_file save_path, :type=>'text/pdf
This code will be more than enough if you just want to render the pdf:
def show
respond_to do |format|
format.html
format.pdf do
render pdf: 'file_name',
template: 'example/pdf_view.pdf.erb',
layout: 'layouts/application.pdf.erb'
end
end
end
If you want to save as pdf:
def save
pdf = WickedPdf.new.pdf_from_string(
render_to_string(
template: 'example/pdf_view.pdf.erb',
layout: 'layouts/application.pdf.erb'))
send_data(pdf,
filename: 'file_name.pdf',
type: 'application/pdf',
disposition: 'attachment')
end
I have a rails app that uses Recurly. I am attempting to download a PDF and render it in the browser. I currently have a link:
link_to 'Download', get_invoice_path(:number => invoice.invoice_number)
The associated controller has the get_invoice method that looks like so:
def get_invoice
begin
#pdf = Recurly::Invoice.find(params[:number], :format => 'pdf')
rescue Recurly::Resource::NotFound => e
flash[:error] = 'Invoice not found.'
end
end
When I click the link I get the PDF rendered in my console in binary form. How do I make this render the PDF in the browser?
You don't render the PDF to the browser, you send it as a file. Like so:
# GET /something/:id[.type]
def show
# .. set #pdf variable
respond_to do |format|
format.html { # html page }
format.pdf do
send_file(#pdf, filename: 'my-awesome-pdf.pdf', type: 'application/pdf')
end
end
end
The HTML response isn't needed if you aren't supporting multiple formats.
If you want to show the PDF in the browser instead of starting a download, add disposition: :inline to the send_file call.
Assuming the PDF is saved in memory, use the send_data to send the data stream back in the browser.
def get_invoice
#pdf = Recurly::Invoice.find(params[:number], :format => 'pdf')
send_data #pdf, filename: "#{params[:number]}.pdf", type: :pdf
end
If the file is stored somewhere (but this doesn't seem to be your case), use send_file.
How to convert ruby file in word file i.e (docx file). For pdf, we prawn gem. But is there any gem for word file. I am trying to convert my html file in word file so that it can be editable for user too. What should do in that case ? I was planning to convert that file in word file. Will it be possible or not.
If you are using Rails:
in initializers/mime_types.rb:
Mime::Type.register 'application/vnd.ms-word', :msword
in your controller:
say you want to export show action:
def show
#item = Item.find params[:id]
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #item }
format.msword { set_header('msword', "#{#item.title}.doc") }
format.pdf do
render :pdf => 'Coming soon...', :layout => false
end
end
end
define set_header in application_controller.rb:
def set_header(p_type, filename)
case p_type
when 'xls'
headers['Content-Type'] = "application/vnd.ms-excel; charset=UTF-8'"
headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
headers['Cache-Control'] = ''
when 'msword'
headers['Content-Type'] = "application/vnd.ms-word; charset=UTF-8"
headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
headers['Cache-Control'] = ''
end
end
now define a show.msword.erb #you can use any template handler like haml etc.
YOUR HTML HERE TO EXPORT TO DOC
AS LIKE NORMAL ERB TEMPLATE
Use htmltoword gem.
https://github.com/nickfrandsen/htmltoword
it hasn't been updated since November 2015, but works well.
I have configured a custom mime type:
ActionController::Renderers.add :csv do |csv, options|
self.content_type ||= Mime::CSV
self.response_body = csv.respond_to?(:to_csv) ? csv.to_csv : csv
end
and a respond_to block in my controller:
respond_to do |format|
format.html
format.csv { render :csv => csv_code}
end
Using Firefox and Chrome, the .csv renders to a file which is downloaded. Using Safari the .csv is rendered as a view: How can I change this and force it to download as a file?
See a screen shot of the problem:
Try
respond_to do |format|
format.html
format.csv do
response.headers['Content-Type'] = 'text/csv'
response.headers['Content-Disposition'] = 'attachment; filename=thefile.csv'
render :csv => csv_code
end
end
if this doesn't work, try using
send_file "path/to/file.csv", :disposition => "attachment"
The way I have this working in an old Rails 2 app is using send_data instead of render in the controller. E.g.:
def csv
... # build data
send_data csv_data_as_string, :filename => "#{filename}.csv", :type => 'text/csv'
end