Show image uploaded in rails - ruby-on-rails

I followed this tutorial http://ryan.endacott.me/2014/06/10/rails-file-upload.html
to make an upload images without using gems .
But it does not teach how to display the image.I 've tried several ways , but without success.

Make sure to add disposition: "inline" to the send_data method as well as the type of file in order to display an image instead of downloading it, as documented here. http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_data
def show
#document = Document.find(params[:id])
send_data(#document.file_contents,
type: #document.content_type,
filename: #document.filename,
type: 'image/png',
disposition: "inline")
end
Then in whatever/your/path/is/show.html.erb
<%= image_tag url_for(controller: "documents",
action: "show",
id: #document.id) %>
This article may be helpful (https://www.safaribooksonline.com/library/view/rails-cookbook/0596527314/ch15s04.html):
For a browser to display binary image data, it needs to be instructed that the data is an image. Specifically, it needs to be told that the content type of the data is something like image/gif. Providing a filename gives the browser something to name the data, should it be downloaded and saved by the user. Finally, the disposition specifies whether the file will be displayed inline or downloaded as an attachment. If its disposition is not specified, it’s assumed to be an attachment.
I hope that helps!

Related

convert SVG code to format to attach to user in Rails

Essentially, in my app users can create a custom svg element using js (stimulus).
My user.rb model has:
has_one_attached :picture
in my attach_image_controller.js I can access the svg code:
<svg>
<-- blah blah >
</svg>
What is the best way to transform this code into a format that can be attached in my user_controller.rb?
I have tried turning the code into a blob and creating an object url, but I haven't been able to then attach it to a user (see below attempt)
attach_image_controller.js
var testsvg = `<svg>
<-- blah blah >
</svg>`;
var blob = new Blob([testsvg], {type: "image/svg+xml"});
var url = URL.createObjectURL(blob);
console.log(url); // returns: blob:http://localhost:3000/15107c0d-b794-4be6-a1e0-2cf9e8f49174 and results in routing error
// As there is a routing error, this url can't be used as per below
and then when passed to the user_controller.rb:
user_controller.rb
#url = params[:url]
#user = current_user
file = URI.open(#url[5..-1])
#user.picture.attach(
io: file,
filename: #url[5..-1],
content_type: 'image/svg+xml')
Edit:
To make things more complicated, in some cases, users have the ability to upload and attach an image, or generate a svg code that renders in the DOM, but I want to be able to attach both the SVG code and the uploaded image.
The typical use case for attachments is when we wish to associate an uploaded file (often an image, e.g. jpg) with a model.
However the svg is an html snippet, it's a string comprised of a single html element (<svg>... </svg>). So you might consider simply including it as a string column in your User model. Remember, though, that you need to declare it html_safe before it will render correctly. So if you are using erb, you'll have <%= user.svg_image.html_safe %>.

send_file in rails does not download to browser - instead loads in browser window directly [duplicate]

This question already has an answer here:
Force browser to download file instead of opening it
(1 answer)
Closed 5 years ago.
I have the following in my .erb:
<%= link_to 'Download PDF', planners_download_pdf_url %>
I have the following method to respond:
def download_pdf
send_file(
"#{Rails.root}/Thing/ex/example.xls",
filename: "mything.xls",
type: "application/xls"
)
end
My routes has:
get '/planners/download_pdf'
When I click my link, the method does get invoked. My problem is that is doesn't download to the browser. Instead, it takes the tab I have open in the browser and dumps the file as HTML. Like... have you ever seen an Excel file opened in notepad? It does that. See below:
How do I get this to instead download the file?
You need to add disposition: 'attachment' to your send_file option hash (or at least ensure that you do not have disposition: 'inline' set, since 'attachment' should be the default).
If this is not the issue, if you are using Turbolinks, as mentioned in other answers you need to disable Turbolinks on the link by setting data-turbolinks="false" in your link element (e.g.: data: {turbolinks: false} in your link_to tag helper).
Finally, here are some other things to try if this doesn't work:
Set type to 'application/vnd.ms-excel', the valid MIME type for XLS files.
Set the download="mything.xls" html5 attribute on the link tag directly (e.g.: download: 'mything.xls' in your link_to tag helper.

How to display an image using a different filename than the physical filename?

In my image hosting webapp I created a hackish way for image de-duplication to save on storage space by having an image.rb model with paperclip to store physical images and a second model imagelink.rb to store image names which link to the physical image. So in my imagelink model I use "belongs_to: image" and add an index on the imagelink to image_id of the image. The naming of the image and imagelink is simply an encoded version of the ActiveRecord ID.
When uploading the image I simply check it's md5sum to see if the image already exists if it does exist then I create a new imagelink ID and use the image ID of the original image. Otherwise I save the image and create a new image ID. This allows me to have a physical image like "vb56.jpg" and an encoded imagelink like "vb56.jpg" as well as a second imagelink like "4gb7.jpg" which also uses the physical image "vb56.jpg"
So naturally now I want to display the original physical image "vb56.jpg" but using the name "4gb7.jpg" when being accessed from the "4gb7.jpg" imagelink. I can achieve this by making another request for each imagelink which would look something like this:
images_controller.rb
before_action :set_image, only: [:show, :show_direct]
def show_direct
path = #image.image.image.url
url = Rails.root.join('uploads' + path)
send_file url, type: #image.image.image_content_type, disposition: 'inline'
end
def set_image
#image = ImageLink.decode(params[:id])
raise 'image not found' if #image.nil?
end
image_view.html.erb
<%
id = #image.encoded_id
ext = #image.image.extension
%>
<img src="<%= MYAPP::DOMAIN %><%= id %>.<%= ext %>" class="image-display" />
So two problems doing it this way is 1) This is probably going to create slowness as well as tons of requests to the rails server for each image displayed on a page. 2) This is messing up the way I store session[:previous_url] for logging in with devise which is "session[:previous_url] = request.fullpath" since each image is a request it's storing the last requested image as the previous_url instead of the actual page the user is on.
Is there a way I can display the image without making tons of requests like currently doing? Doing the proper way with <%= image_tag(#image.image.image.url) %> to display the physical image will show the image as the original filename but I'd like it to show the filename as the imagelink name so that to the user the physical image name will always match the imagelink name.
Also am I doing session[:previous_url] wrong? Is there a better way to do it to capture the page URL rather than the URL of other requests coming from within the page?

Change browser tab title to file name when send_file pdf

In my project I'm using Carrierwave to upload files like doc, and pdf.
In case I want to download a pdf my controller do
send_file #document, :disposition =>
'inline', :type => 'application/pdf'
And this works fine, displays the pdf file in browser and the url I get is /documents/file_name and it's fine too. But I want to set the "headers title" or "url title" so in the browser's tab shows the file_name instead myapp.com/documents/file_name
Is there a simple way to do that?
Unfortunately it is not possible as you describe.
The tab title is taken from the PDF documents metadata, specifically the Title attribute.
If you usually generate your document with Prawn you can do:
Prawn::Document.generate(my_filename, info: {Title: my_title})

is it possible to show only a part of the image URL in rails?

I am using Carrierwave and S3 to allow people to upload images and the image URL is displayed as "https://myapp.s3.amazonaws.com/image/53/98ccfeca46.jpg".
I would like to do one of two things.
I would like to show just
"/image/53/98ccfeca46.jpg"
or 2. Use CName to rename the URL to not show "s3.amazonaws.com" so that the image URL will be
https://myapp.com/image/53/98ccfeca46.jpg
How can I achieve these? Is it possible to cut the image URL right after .com?
I am using <%= link_to xyz.image % > to display the URL.
You could create a helper method for displaying the url, and use string sub to cut off the first part of the url.
So in your helpers folder, in the helper for the corresponding model, you might have a function like
def show_url(url)
return url.sub("https://myapp.s3.amazonaws.com", "")
end
And then in your helper you would have <%= link_to show_url(xyz.image) %>
Or indeed something similar, but using regular expressions
def show_url(url)
return url.match(/.com(.+)/)[1]
end
If you're using carrierwave, you can call .path to retrieve the path of the image. I tried this locally and it worked fine but I'm not sure if it will work in production. Try this:
<%= link_to xyz.image.path %>
Alternatively, you can use CloudFront to server you S3 files, which allows you add a bunch of custom CNAMEs to your distribution, so you can have assets.myapp.com/xyz.jpg

Resources