Rails Controller - format.png - ruby-on-rails

Trying to get a controller block in rails to work. When responding to a url I want to show the .png file associated with the model.
respond_to do |format|
format.html { render :blank }
format.json { render json: #play }
format.png do
send_data data, :type => "image/png", :filename => 'screenshot.png'
end
Data is working fine and is a 200Kb file. The issue is when I go to the url:
http://localhost:8080/plays/testing1.png
it brings me to a blank page (I created show.png.erb and have nothing in there). Not sure how to get the png file to either be shown inline or downloadable.
Thanks for any help

Try using Conent-Disposition, you can either set it to attachment or inline.

Old question but i've been struggling with the same problem for a few hours so in-case anyone finds this in the future:
I was also getting the same problem where a document was being generated in Chrome with a broken image and tag i.e. <img style="-webkit-user-select: none" src="http://localhost:3000/open/28">. Also in Firefox I was getting an error saying there was a problem with the image.
The solution: I changed send_data to send_file which gave me the following code:
respond_to do |format|
format.png { send_file img ,type: "image/png", disposition: 'inline' }
end
More info about send_file here
After that, the routes responded by serving the PNG images without the broken image tags.
Hope that helps someone out.

Related

RAILS - Generate PDF from HTML with GROVER

I want to use GROVER to export same ERB/HTML pages from my application as PDF.
It works, but the generated PDF seems to be missing the styles and formatting, no CSS seems to be processed.
Here my code within the controller:
html_string = render_to_string(
{
template: 'users/show.html.erb',
locals: { id: params[:id] }
})
pdf = Grover.new(html_string, format: 'A4').to_pdf
respond_to do |format|
format.html
format.pdf do
send_data(pdf, disposition: 'inline', filename: "Show_ID_#{params[:id]}", type: 'application/pdf')
end
end
My question is, how I can persuade GROVER also to process the CSS files ?
I had the same problem where my layout was rendered without the CSS. I was able to resolve the issue by adding the display_url option in Grover.
In local development this would be for example:
pdf = Grover.new(html_string, format: 'A4', display_url: "http://localhost:3000").to_pdf
You need to change your display_url depending on your environment.
If this does not work, make sure the html_string that you are rendering actually includes the correct markup. You can render out the html_string as HTML to verify all markup is included.

Creating PDFs with Prawn - missing attribute error

I'm working on PDF creation in my rails application. I found PDFkit didn't necessarily do what I wanted to do, so I figured I'd test out Prawn.
I added it to my controller using this code:
def show
#document = Document.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new(#document)
send_data pdf.render, filename:"1",
type: "application/pdf",
disposition: "inline"
end
end
end
But using this I get a Missing Attribute error. I'm assuming this is because my model is also named Documents and conflicts with the Prawn::Document.new command?
Can I just not have a documents model and use Prawn - or is there something I'm missing here?
I don't think it's about Document vs Prawn::Document, but I've never seen someone pass an ActiveRecord instance to Prawn::Document.new. I think that expects an options hash, right? And calling render before giving it any content seems suspicious. What is the actual stack trace?

Rails download http response/displayed site

Instead of displaying the xml file rendered by the index.api.rsb file in my browser, i want to download it. To me this sounds very simple, but I cant find a solution.
I tried the following in the controller-method:
def split
if params[:export] == "yes"
send_file *here comes the path to xml view*, :filename => "filename", :type => :xml
end
respond_to ...
end
The result is a MissingFile exception...
Thanks in advance
Note that :disposition for send_file defaults to 'attachment', so that shouldn't be a problem.
If you have a MissingFile exception, that means the path is incorrect. send_file expects the path to an actual file, not a view that needs to be rendered.
For your case, render_to_string might be what you need. Refer to this related question. It renders the view and returns a string instead of setting the response body.
def split
if params[:export] == "yes"
send_data(render_to_string path_to_view, filename: "object.xml", type: :xml)
end
end
To force it to download it, add :disposition => attachment to your send_file method.
Source: Force a link to download an MP3 rather than play it?

How to trigger download with Rails send_data from AJAX post

I'm trying to use send_data to return a PNG image as the response for a ajax post request. How do I get the browser to trigger a download on the success callback?
Details
I'm generating a large base64 image using canvas.toDataURL(), and then posting it to Rails (v3.2.6). Rails decodes it to a binary PNG, and sends the image back to the client.
I've also tried send_file but it has the same issue.
Other options
Download image client side: We can't do this because (1) Safari crashes on large base64 URLs, and (2) Safari does not yet support the download attribute on anchor tags which I would need to specify the downloaded image filename.
Use a $.get instead of $.post: We can't do this because we need to send our canvas.toDataURL() with the request to the server. GET requests URIs have size limitations.
create a function in controller
def ajax_download
send_file "path_to_file/" + params[:file]
end
and then in controller action
respond_to do |format|
#java_url = "/home/ajax_download?file=#{file_name}"
format.js {render :partial => "downloadFile"}
end
and make a partial in view folder name with _downloadFile.js.erb and write this line
window.location.href = "<%=#java_url %>"
You can't download a file to disk from JS. It's a security concern. See the blog post below for a good workaround.
http://johnculviner.com/post/2012/03/22/Ajax-like-feature-rich-file-downloads-with-jQuery-File-Download.aspx
Do not just copy and paste the accepted answer. It is a massive security risk that cannot be understated. Although the technique is clever, delivering a file based on a parameter anybody can enter allows access to any file anybody can imagine is lying around.
Here's an example of a more secure way to use the same technique. It assumes there is a user logged in who has an API token, but you should be able to adapt it to your own scenario.
In the action:
current_user.pending_download = file_name
current_user.save!
respond_to do |format|
#java_url = "/ajax_download?token=#{current_user.api_token}"
format.js {render :partial => "downloadFile"}
end
Create a function in the controller
def ajax_download
if params[:token] == current_user.api_token
send_file "path_to_file/" + current_user.pending_download
current_user.pending_download = ''
current_user.save!
else
redirect_to root_path, notice: "Unauthorized"
end
end
Make a partial in view folder name with _downloadFile.js.erb
window.location.href = "<%=#java_url %>"
And of course you will need a route that points to /ajax_download in routes.rb
get 'ajax_download', to: 'controller#ajax_download'

Sending an image through JSON data

noobie here hope you guys don't mind! Im trying to query my user/id/pictures.json but all it returns are attributes cus i did a generic format.json {render :json => #photo.to_json()}. My question is how can i create and encapsulate the actual data from the images, so my client can turn that data in to an image? And also what do i need to create(attribute wise) besides the path of image(say you only had useless attributes eg: height content_type, description, thumbnail file_name)?
this is what im trying in my index.json.erb so far
}
<% #photos.each do |photo|%>
data: <%= StringIO.new(Base64.encode64(photo.public_filename(:large))) %>
<%end%>
}
i am getting back
{
data: #<StringIO:0x1058a6cd0>
}
which is not the IMGdata im looking for
looking for
Have a look at Data-URIs.
They essentially are Base64-encoded entities (documents) formatted as a URI
[{ "name":"red dot", "data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="}, ...]
[UPDATE]
You need to read the file and encode it as Base64 (you also need to strip the newlines away in rails 2.3.x)
data = ActiveSupport::Base64.encode64(File.read("/images/image1.png")).gsub("\n", '')
uri = "data:image/png;base64,#{data}"
I think you are using Ruby on Rails, aren't you?
Then there are some steps needed to download an image (e.g. a png):
Create a mime type
Go to config/initializers/mime_types.rb and insert Mime::Type.register "image/png", :png at the end.
Create an image
For example, you could use the gem Chunky_PNG to create an image, see at http://rubygems.org/gems/chunky_png and https://github.com/wvanbergen/chunky_png/wiki
Prepare your controller
You have to tell your controller, that it can accept pngs. Modify your controller the following way
class UsersController < ApplicationController
respond_to :json, :png
def show
# your own stuff
# ...
respond_with(response) do |format|
format.json
format.png do
send_data ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT), :type =>"image/png", :disposition => 'inline'
end
end
end
end
This will create a fully transparent image. If you want to draw something in this, look at the Chunky PNG docs.
It's up to the client how to render it really. This works for me, maybe worth a try.
render json: #thumbnail, type: :jpeg, content_type: 'image/jpeg'

Resources