rubyzip streaming over Rails 4 Live ActionController - ruby-on-rails

I want to create a zip archive on the fly while streaming it over the new Rails Live API. My problem at this point isn't the creation of the zip and sending it to the browser. It's more the problem to creating the zip on-the-fly for sending it over the rails response stream. The rubyzip documentation doesn't seem to be very well in some points for the streams.
here is the code that already works for creating and sending the file to our server (it doesn't use the ActionController Live API).
t = File.open("#{path}/#{zipfile_name}", "w")
Zip::OutputStream.open(t.path) do |zos|
# recursive method for building the zip structure in our system
stream_files(zos, params[:files], folder, "")
end
send_file t.path, :type => 'application/zip',
:disposition => 'attachment',
:filename => "#{zipfile_name}.zip"
t.close
Has anyone the same problem and got solved it already?

Related

download all tracks from current_cart line_items in rails

I am using Rails 4.0.0 and Ruby 2.0.0
My app is for downloading mp3 files from s3 storage. Downloading a single mp3 track works, however downloading all selected tracks in current_cart is not working.
my controller is
tracks_controller.rb
def mp3_download_all
if !current_cart.line_items.blank?
current_cart.line_items.each_with_index do |track,i|
puts track.track.inspect
track.track.increment! :download_count
send_file(Paperclip.io_adapters.for(track.track.mp3_track_file).path, :type => track.track.mp3_track_file_content_type, :disposition => "attachment", :filename => track.track.mp3_track_file_file_name)
end
end
end
It's downloading only the last track.
Thanks
You can't really do this server side - one http request results in one response, i.e one file (to my knowledge browsers don't consistently support multipart mime responses).
Your best bet is probably to create a zip containing all the files and send that (the rubyzip gem makes this very easy). You might want to do this in some sort of background job (delayed_job, sidekiq etc)

How can I view a pdf file that is encoded (as base64) in my database?

I currently have a site on heroku and am using postgreSQL. When I upload pdf files to the database, I encode them to base64 and save them as text. I can click a link decode the file and download it without a problem; however, I'm having trouble having a page where I have an iframe with the pdf file within it. How can I feed the freshly decoded file to iframe? Even without iframe, how can I just decode the file and have it as a page?
I'm thinking that I could create a pdf controller, decode the file and have show open the file, but I can't even get that to work.
Thanks for the help!
Edit: Here's what I have so far.
def create
#course = Course.find(params[:note][:id])
params[:note][:content].tempfile = Base64.encode64(open(params[:note][:content].tempfile).to_a.join)
params[:note][:filename] = params[:note][:content].original_filename
params[:note][:contenttype] = params[:note][:content].content_type
#note = #course.notes.build(:content => params[:note][:content].tempfile, :filename => params[:note][:filename],
:contenttype => params[:note][:contenttype])
if #note.save
flash[:success] = "File Uploaded!"
redirect_to root_path
end
This saves the file as base64 without a problem. I'm not too sure about the next part though.
def show
#note = Note.find(params[:id])
#notecon = #note.content
decoded_data=Base64.decode64(#notecon)
file_name = "test"
#temp_file = Tempfile.new("filename-#{Time.now}")
File.open(#temp_file, 'wb') {|f| f.write(decoded_data)}
end
Now, in the view, I have no clue what to put as the filepath.
<iframe src="http://docs.google.com/gview?url=http://localhost:3000/app/views/notes/test&embedded=true"
style="width:718px; height:700px;" frameborder="0"></iframe>
I can't even figure out how to post a pdf file that's saved on my drive.
Thanks again!
You can use the
send_data
method in action controller to send the file to the browser. You will need to set the content type, how it should be displayed by the browser etc.
send_data(#pdf, :type => 'application/pdf', :filename => "myfile.pdf", :disposition => "inline"
:deposition=>'inline' instruct the browser to display it inside the browser.
You can find similar examples here where they upload an image to the database
http://over9000.org/rails/saving-ruby-on-rails-attachments-as-blobs
https://gist.github.com/macek/610596
Rails: Storing binary files in database
Consider storing the pdf to an Amazon S3 bucket or other cloud storage . PaperClip gem can do it trasparently for you. https://github.com/thoughtbot/paperclip‎ . Paperclip can save to database too.
If you still plan to go with database storage, be aware of its de-merits
Rails: Storing binary files in database

Is there a way to have a resque job push a generated pdf directly to the browser?

I need to have a system where a PDF is generated dynamically, asynchronously, and directly pushed to the browser, no disk storage is available. Getting resque to use prawn seems easy, its taking that data and sending it to the browser without storing it somewhere first, I can't find anything online. I thought about Faye, but can Faye handle pushing a PDF to the browser?
I've done this before in .net where i have an iframe's src attribute set to a service that returns a stream. The service aslo flips the http header to content-inline so that the browser doesn't try to download it but instead will try to render it inline. If you try to do this it wont work if the browser doesn't have a pdf plugin (must modern ones will but you always have that guy using IE6 yet) I don't know a lick of ruby but think you should be able to do something similar, or at least but an iframe on a page that targets a service written in something else.
u can use "PDFkit" for it.
the sample code is
def some_action
...
respond_to do |format|
format.html
format.pdf do
generate_pdf(file.html.haml, :css => [array of css file names that need to be added])
end
end
end
in application controller -
def generate_pdf(template, options={})
html = render_to_string(template, :layout => false)
kit = PDFKit.new(html, :orientation => 'Landscape')
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/default_css1.css"
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/default_css2.css"
# Add CSS
if options[:css]
options[:css].each do |css|
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/#{css}.css"
end
end
send_data(kit.to_pdf, :filename => 'latest.pdf', :type => 'application/pdf', :disposition => 'inline')
end
How big those PDFs are? Your database has BLOB columns (if you don't have storage, you are not using SQLite...) and you can store the resulting PDF in it.
Or you can store the resulting PDF in the Redis DB. Or save it in S3.
On the other end, the browser will be polling (with ajax) every now and then to know whether the PDF is complete, and as soon as it is ready it will download it and show it to the user.

Returning files from rails

Beginner rails question: How does one return a file from a controller in rails?
I'm familiar with returning/rendering JSON objects. However I've never returned/rendered a file w/ an arbitrary extension.
From reading around SO it sounds like render :nothing => true could help. I'm just looking for some guidance or relevant documentation.
You can use the built-in rails send_file or send_data method.
To stream a file (e.g. for a file proxy endpoint), use send_file:
send_file("#{RAILS_ROOT}/path/to/file/on/server",
:filename => "client-suggested-filename",
:type => "mime/type")
To stream generated data (e.g. for a generated pdf), use send_data:
send_data(your_data,
:filename => "client-suggested-filename",
:type => "mime/type")
The file extension and mime type don't have to match up, but they probably should just to conform to end user expectations. For example, if you are sending with a mime type of application/pdf, you should really set the :filename to something.pdf.
If you're not sure what the mime type is for the file you are sending, you can check this wikipedia page or use the mime-types gem. (Or if you are reading from a database that stores the mime type, use that).

Direct downloading a xls file without writing it to the directory by Spreadsheet gem

I am using this Spreadsheet gem to export xls file.
I have the following codes in my controller:
def export
#data = Data.all
book = Spreadsheet::Workbook.new
sheet = book.create_worksheet :name => "data"
contruct_body(sheet, #data)
book.write "data.xls"
end
In this way, I can fill in the data and save it in the root directory.
But I want to download it instead of save it. How could I modify the code so that the user prompted to select his local directory to save the file? (better if without saving a copy in the server side)
Please help!
You can send it to the browser without saving it as a local file at all as follows
spreadsheet = StringIO.new
book.write spreadsheet
send_data spreadsheet.string, :filename => "yourfile.xls", :type => "application/vnd.ms-excel"
You could try this code
book.write "data.xls"
send_file "/path/to/data.xls", :type => "application/vnd.ms-excel", :filename => "data.xls", :stream => false
# and then delete the file
File.delete("path/to/data.xls")
Passing :stream => false to send_file will instruct Rails to copy the entire file into memory before streaming, so using File.delete immediately after send_file would be fine since send_file returns immediately without waiting for the download to complete. Having said that, with very large files you may see some memory bottle necks depending on the amount of memory available.
HTH
I understand this is insanely old, but I was looking for it so someone else might be.
This is the answer. (I'm using Sinatra.)
https://github.com/zdavatz/spreadsheet/issues/125#issuecomment-370157753
The case happen on mybody.
I used the ajax request by remote::true to export excel file, nothing display on browser without any error message on console.
Delete the remote params from the form, it works well.

Resources