Rails; save a rendered views html content to file - ruby-on-rails

I'm trying to create a view with a download link to download the html source?

#Peter 's solution worked for me. Here is a code sample:
View:
<%= link_to 'download this page', object_path(#object, :download => true) %>
Controller:
def show
# ...
if params[:download]
send_data(render_to_string, :filename => "object.html", :type => "text/html")
else
# render normally
end
end

You can use render_to_string instead of render, which will give you the page, then to download it use send_data.
More on render to string here, and more on send_data here.

Related

how to display encrypted images in the view with Lockbox in ruby on rails?

Rails docs and Lockbox docs say to do this in a controller if I want to stream data to the browser:
def license
send_data user.image.front.read, :type => user.image.front.content_type, :disposition => 'inline'
end
This shows the file against a black background. But what if I have a bunch of files that I want to display in the view? One for each user?
def license
#users = User.all
#send_data wont work because i need to call it for each user displayed in the view
#send_data user.image.front.read, :type => user.image.front.content_type, :disposition => 'inline'
end
I want to be able to do this in the view:
<% #users.each do |user| %>
#display user.identity_document.front
<% end %>
I can't use send_data outside the controller, so is there another method I can use that would do what I need?
You'll want to use one action for the view and another to serve the images.
class UsersController < ApplicationController
def index
#users = User.all
end
def front_image
user = User.find(params[:id])
image = user.identity_document.front
send_data image.read, type: image.content_type
end
end
And in the index view:
<% #users.each do |user| %>
<%= image_tag front_image_user_path(user) %>
<% end %>
(don't forget to hook up the routes as well)
What do you mean by showing a bunch of PDF files in the view? Are you trying to show more than one PDF content as a single PDF by merging them? If that's the case then you have to merge all the PDF's content and stream the data to the browser.
For merging multiple PDF's you can make use of Ruby gem combine_pdf or you can make use of python pyPDF2 to mege the PDF's separately.

How to download file with id params?

Hello I try to download a jpeg image on rails by verifying that the Post exists and by recovering its id in parameter.
I try something but i got a error... I show you:
def download
send_file '/public/uploads/posts/#image/image.jpg', :type => 'image/jpeg', :disposition => 'attachment', :x_sendfile => true
end
private
def set_image
#image = Post.find(params[:id])
end
In my controller I have to in my routes get download.
And my link_to is:
<%= link_to "Download", download_posts_path %>
But rails say to me "Couldn't find Post without an ID".
I don't understand why... He dont't have the id but I dont't know why ?
Assuming you use set_image in a before_action filter.
First you should pass the post instance or id to your route helper :
If your route takes a param e.g. /posts/:id/download :
<%= link_to "Download", download_posts_path(#post) %>
<%= link_to "Download", download_posts_path(#post.id) %>
If not you can pass it with a query parameter e.g. posts/download/?id=1
<%= link_to "Download", download_posts_path(id: #post.id) %>
Both solution will provide you a params[:id] in your controller. Otherwise params[:id] will be nil and find raises an error.
Then there's something wrong in the download action as #DileepNandanam pointed out. You're not using your Post instance (#image) at all, you're just passing send_file a string containing "#image", not the variable but just a string. You may want to use interpolation to build a valid path to your image. For example if your #image has a :name which could be "image.jpg" you would do it like this:
send_file "/public/uploads/posts/#{#image.name}"
Or you could name your images with the post id like 13.jpg then you'll do :
send_file "/public/uploads/posts/#{#image.id}.jpg"
Or even create separate forlders with post's ids :
send_file "/public/uploads/posts/#{#image.id}/image.jpg"
send_file "/public/uploads/posts/#{#image.image_file_name}/image.jpg", :type => 'image/jpeg', :disposition => 'attachment', :x_sendfile => true
The method image_file_name may varies depends on the attachment you have specified on model
A better way is to use the url for attachment like
send_file #image.image.url(:original)

Ruby on Rails send_file doesn't work until i refresh the page?

I am working on a Rails server which I can download my locally stored movies and anime etc from. This is kind of working but when I click the download link I have to refresh the page in order for the download to actually start.
This is the controller that handles the download:
class DownloadController < ApplicationController
def index
#title = params[:title]
#name = params[:name]
#path = '/media/sf_Anime,_VN,_LN/Watching, not watched yet/'+#title+'/'+#name
send_file( #path )
end
end
and this is the link that links to that controller:
<% #episodes.each do |x| %>
<p> <%= x %><%= link_to " Download",
{controller: 'download', action: 'index', title: #title, name: x } %> </p>
<% end %>
edit:
I did some testing today and noticed that the download links work instantly if i try to send a smaller file (text or image). I also noticed that the download links actually works for the movies aswell but it takes 20-30 seconds for the download to start.
Do you have any idea of what would cause this delay?
Are you using turbolinks? Turbolinks apparently doesn't play nicely with send_file (https://github.com/rails/turbolinks/issues/182). Try adding "data: { no-turbolink: true }" (or "'data-no-turbolink'=>true") in the link_to helper, e.g.:
<%= link_to "Downloadable File", downloadable_file, data: { no-turbolink: true } %>
See also: Rails 4, asset pipeline causes user downloadable files to be downloaded twice, rails won't send_data as file, Ruby on Rails send_file, code in controller action running twice
Edited to reflect comment below. I would simple add a concern for handling downloads and then use
include Concerns::Downloads
to handle your download request. the routes.rb would look like this.
resources :movies do
member do
post 'download'
end
and in the view
<%= link_to 'Download', {:controller => 'movies', :action => 'download'}, {:method => :post } %></a>
Move the file to public folder
add only file name into link_to
<%= link_to "Downloadable File", "/"+filename, %>
Try setting the disposition to attachment in send_file:
class DownloadController < ApplicationController
def index
...
send_file( #path, :disposition => 'attachment' )
end
end
The issue may be that your browser is trying to open the file itself - :disposition => 'attachment' prompts the browser to download the file, even if it thinks the file is something that it can open.

Rails download file from show action?

I have an uploader which allows you to upload documents. What I want to do is trigger a download for the document when you view its show action. The url would be something like:
/documents/16
This document could be .txt, or .doc.
So far, my show action looks like this:
def show
#document = Document.find(params[:id])
respond_with(#document) do |format|
format.html do
render layout: false, text: #document.name
end
end
end
How would I go about achieving this?
Take a look at the send_data method:
Sends the given binary data to the browser. This method is similar to render :text => data, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data. You may also set the content type, the apparent file name, and other things.
So, I think in your case it should be something like this:
def show
#document = Document.find(params[:id])
send_data #document.file.read, filename: #document.name
end
I created a new method in my controller for downloading a file. It looks like this. Stored_File is the name of the archived file and has a field called stored_file which is the name of the file. Using Carrierwave, if a user has the access/permissions to download the file, the URL will display and then send the file to the user using send_file.
Controller
def download
head(:not_found) and return if (stored_file = StoredFile.find_by_id(params[:id])).nil?
case SEND_FILE_METHOD
when :apache then send_file_options[:x_sendfile] = true
when :nginx then head(:x_accel_redirect => path.gsub(Rails.root, ''), :content_type => send_file_options[:type]) and return
end
path = "/#{stored_file.stored_file}"
send_file path, :x_sendfile=>true
end
View
<%= link_to "Download", File.basename(f.stored_file.url) %>
Routes
match ":id/:basename.:extension.download", :controller => "stored_files", :action => "download", :conditions => { :method => :get }

How can i display an error for ajax in rails

I am trying to display an error message of flash in Ajax using Rails but it doesn't display it, and I have tried several ways to do it but I just can't get it right.
Here is my form to display my errors:
#flash-error.flash-error{:style => "display: none"}
#flash-notice.flash-info{:style => "display: none"}
%h3 New Document
- form_for(:repo_document, :url => {:all_categories => #repo_categories, :action => "create", :format => "js", :query => params[:query]}, :html => { :id => "repo_document_form", :multipart => true, :target => 'upload_frame'}) do |form|
Here is the controller:
if !params[:stands]
respond_to do |format|
format.js do
responds_to_parent do
render :update do |page|
page.show "flash-error"
page.replace_html "flash-error","Please select stands you want to grant permission to view this stand."
end
end
end
return
end
end
What am I doing wrong?
js.rjs to the rescue
def action
#true = params[:stands]
respond_to |format|
format.js
end
end
in action.js.rjs:
if #true
# do true stuff
else
page.replace_html 'error_block_dom_id', :text => 'This is my error'
end
and the original view file that you make the ajax call from:
#nothing here due to no errors - errors will appear if they happen
<div id="error_block_dom_id"></div>
No overarching reason to use the flash - just update a DOM object with the error content.
A possible solution would be to send an ajax call to an action in a controller and set your flash messages in that action
Flash is only going to display on the next time the page is loaded. It doesn't update through AJAX. One of the caveats of AJAX is that it doesn't deal with file uploads...
See this for more details; http://guides.rubyonrails.org/form_helpers.html#uploading-files
I think the problem might be elsewhere: Element's method show (call of which is generated when You call page.show "flash-error") will not remove display: none css style when it is given inside the external Css file. This is a quotation from older version of Prototype's API Documentation.
So try to add display: none as inline style of Your div's. I hope it will help!

Resources