Display all format files in Rails using send_data - ruby-on-rails

I have an application which has to display files of different formats. The list of formats maybe limited, but they consists of different formats. They can be .pdf, .docx, .odt, .png etc.
In my controller the show action looks like the following . The "content" is rendered from a given website which contains files of different formats.
def show
send_data(content, :disposition => 'inline', :type => format_finder(params[:format]))
end
def format_finder(format)
formats={"pdf" => "application/pdf",
"docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"png" => "image/png",
"html" => "text/html",
"odt" => "application/vnd.oasis.opendocument.text",
"ods" => "application/vnd.oasis.opendocument.spreadsheet",
"jpg" => 'image/jpeg'}
if formats.has_key?(format)
return formats[format]
end
end
The problem is that the browser (chrome) is downloading the files instead of displaying them , except for PDF. How do I go about this issue ? Firefox is downloading all the files even if it is PDF.

Related

Rails send_file/send_data - Cannot Read File - After web service call

My Rails 3.1 app makes a web service call to get a pdf file that I then need to send to the browser for download.
The XML response is something like this:
<RenderResponse>
<Result>blahblah this is the file info<Result>
<Extension>PDF</Extension>
<MimeType>application/pdf</MimeType>
</RenderResponse>
I am then trying to convert the "Result" tag to a file as so:
#report = #results[:render_response][:result]
#report_name = MyReport.pdf
File.open(#report_name, "w+") do |f|
f.puts #report
end
finally I try to send to the browser:
send_file File.read(#report_name), :filename => #report_name, :type => "application/pdf; charset=utf-8", :disposition => "attachment"
This yields an error the says "Cannot Read File" and it spits out all the text from the results tag.
If I use send_data as so:
send_data File.read(#report_name).force_encoding('BINARY'), :filename => #report_name, :type => "application/pdf; charset=utf-8", :disposition => "attachment"
The download works but I get a file with 0KB and an Adobe Error that says the file "MyReport.pdf" can't be opened because "its either not a supported file type or it has been damaged".
How can I take the XML response file info, create the file, and stream to the browser?
I found the solution. send_file is the correct stream mechanism to use but I needed to decode the string while writing to the file. I also need to add the 'b' parameter to the File.open call.
This works:
File.open(#report_name, "wb+") do |f|
f.puts Base64.decode64(#report)
end
#file = File.open(#report_name, 'r')
send_file #file, :filename => #report_name, :type => "application/pdf; charset=utf-8", :disposition => "attachment"

Firefox does not Show PDF File Extension on Download

I'm using rails to send a pdf back to the client and in Firefox the file extension is not showing:
My rails code looks like this:
send_data(
pdf,
:type => "application/pdf",
:disposition => "attachment; filename=transcript_#{Time.zone.now.strftime('%m-%d-%Y %H:%M')}.pdf",
# :filename => "transcript_#{Time.zone.now.strftime('%m-%d-%Y %H:%M')}.pdf"
)
I've been trying to set the file name with a combination of the :filename and :disposition key to display the correct filename in the browser. The :filename key doesn't seem to work in Firefox and the :disposition key gives me the picture above.
What do I need to change to get the pdf file extension to be shown in Firefox?
The space (inside of the time format) is throwing off the file name. You need to surround the file name in quotes.
Try this:
:disposition => "attachment; filename=\"transcript_#{Time.zone.now.strftime('%m-%d-%Y %H:%M')}.pdf\"",
^^ ^^
This behavior is explained here: http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download.
The key point being that
[The space] creates an ambiguity when parsing the header for the filename when the browser has to consider the possibility of internationalized filenames. As Internet Explorer does not have to worry about this, it will parse the filename until the end of the line. Mozilla will not.
this will definitely work
send_data pdf.render, filename: 'transcript_#{Time.zone.now.strftime('%m-%d-%Y %H:%M')}.pdf',
type: 'application/pdf',
disposition: "attachment"

Ruby on Rails - send_file is not working

I wrote the following code.
def help_doc
pdf_filename = File.join(Rails.root, "/public/doc.pdf")
send_file(pdf_filename, :filename => "doc.pdf" :type => "application/pdf", :diposition => "inline")
end
It's working, but not as I want. I'd like to view in the browser the pdf, but it's doing download of the document.
I thought that just writing :disposition => "inline" and I could see on the browser the pdf.
Try removing the content disposition. You have a typo in your code, deposition vs disposition, and you're missing a comma after filename.

What is the proper way to serve mp4 files through rails to an Ipad?

We're having trouble serving mp4s that will play on an ipad using a default rails 3 app. The mp4 is served correctly when viewing the route in chrome and other browsers on a desktop.
Here is our code:
file_path = File.join(Rails.root, 'test.mp4')
send_file(file_path, :disposition => "inline", :type => "video/mp4")
We hit 0.0.0.0:3000/video/test.mp4 to view the video and are presented with cannot play icon on the ipad. We've tried modifying various headers "Content-Length", "Content-Range", etc but they don't seem to affect the end result.
We've also tried using send_data to some extent
i.e.
File.open(file_path, "r") do |f|
send_data f.read, :type => "video/mp4"
end
The same video serves fine from the public folder when viewed on the Ipad.
What is the proper way to serve mp4 files through rails to an Ipad?
The problem seems to be that rails doesn't handle http-range requests which ios needs for streaming mp4s.
This was our solution for development, (using thin as our server):
if(request.headers["HTTP_RANGE"]) && Rails.env.development?
size = File.size(file_path)
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
offset = bytes.begin
length = bytes.end - bytes.begin + 1
response.header["Accept-Ranges"]= "bytes"
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}"
response.header["Content-Length"] = "#{length}"
send_data IO.binread(file_path,length, offset), :type => "video/mp4", :stream => true, :disposition => 'inline',
:file_name => file_name
else
send_file(file_path, :disposition => 'inline', :stream => true, :file_name => file_name)
end
Ultimately we will be using nginx XSendfile to serve the assets in our production environment as the above solution is much slower than what we need.

rails send_file and send_data sends out zero byte files

I'm trying to send a pdf back to the user but I'm having serious problem getting send_file and send_data to work. I created the pdf file as follows:
tmp = Tempfile.new('filled')
new_tmp_path = PDFPrint.fill_form_using_pdftk(template_path, tmp.path)
send_file (new_tmp_path, :filename => 'filled.pdf')
The browser prompts for a download, but the downloaded filled.pdf file has zero byte.
I have verified that new_tmp_path does contain a valid pdf (good, filled content)
I have tried this:
File.open(new_tmp_path, 'r') do |f|
send_data(f.read, :filename => "filled.pdf")
end
But this also gives me the same download->zero-byte problem, while the file on server (new_tmp_path) has perfect content.
Regards,
Try sending a simple file to see if it works
send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
Read this thread, I think it has everything you need.

Resources