My application creates customized labels depending on an object's properties (make, model, etc.) and successfully saves them to the server. I'm trying to get it to send_data the image (using to_blob) directly to the browser so the user can immediately open and print the image, instead of saving it to the server first. I'm having a lot of trouble getting the sending to the browser part to work.
I'm using Rails (4.0.0) and rmagick (2.13.4). Please let me know if I can share any other information. Here's the code:
VIEW
<%= link_to fa_icon('qrcode', text: 'Print'),
labels_path(#warranty_item.qr_code, { format: :png }),
method: :post, remote: true, class: 'btn btn-xs btn-warning' %>
CONTROLLER
require 'rmagick'
def create
respond_to do |format|
format.png do
#img = Magick::Image.new(280, 100) { self.background_color = blue' }
#img.format = 'png'
#img_blob = #img.to_blob
send_data #img_blob, filename: 'test_label.png', disposition: 'inline', type: 'image/png'
end
end
end
In Rails' logs, this goes off without a hitch; no errors, no warnings, only a: Sent data test_label.png (0.7ms)
If I run #img.to_blob in the Rails console, it gives me this:
"\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x01 \x00\x00\x00$\x01\x03\x00\x00\x00\x13\xABua\x00\x00\x00\x04gAMA\x00\x00\xB1\x8F\v\xFCa\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xFA\x00\x00\x00\x80\xE8\x00\x00u0\x00\x00\xEA`\x00\x00:\x98\x00\x00\x17p\x9C\xBAQ<\x00\x00\x00\x06PLTE\x00\x00\xFF\xFF\xFF\xFF{\xDC\x99,\x00\x00\x00\x01bKGD\x00\x88\x05\x1DH\x00\x00\x00\x14IDAT8\xCBc`\x18\x05\xA3`\x14\x8C\x82Q#,\x00\x00\x054\x00\x01\xEA\xAF\x9B \x00\x00\x00\x00IEND\xAEB`\x82"
However, if I use the logger, Rails.logger.info #img.to_blob it gives me this:
�PNG
IHDR $�uagAMA��
�a cHRMz&�����u0�`:�p��Q<PLTE����{ܙ,bKGD�HIDAT8�c`�`��Q#,4ꯛ IEND�B`�
Like I'd mentioned above, if I simply save the image, #img.write('test_label.png'), it works perfectly. What am I doing wrong? What am I missing? The code executes, tested in the console it works, but it does not send the image data to the user's browser/downloads file so they can open it. Please help!
It cannot work. Your link with 'remote: true' is an ajax request. You can't download a image to disk from JS. It's a security concern.
read here: enter link description here
Related
In my view, I can display my file attached to the model with Active Storage in a popup like this:
<%= image_tag #image.variant('small') %>
It's working well.
The problem is when I want to use a variant in the link:
<%= image_tag #image.variant('small') %>
The variant code used is:
file.variant(resize:size).processed.service_url
The link seems to be good, but when I click the image, the image is not opened in my JS popup as before but opened in a new browser window. This is very strange.
I shortened the link.
https://bucket.s3.eu-west-3.amazonaws.com/variants/MmsLY3rf8yR9/38a77a69d170464c472f6d36fb3fbc28b284af0cadaa533?response-content-disposition=inline%3B%20filename%3D%22chateau.jpeg%22%3B%20filename%2A%3DUTF-8%27%27chateau-lynch.jpeg&response-content-type=image%2Fjpeg&Signature=29fe7d85fe369ea2335fa8b333d4868d8c2f2c22e1efe
Is-it a "content-disposition" issue ?
Well, this is what I did:
In my Image model, I added an action and used the rails_representation_url() method from url_helpers:
include Rails.application.routes.url_helpers # need this for
include Rails.application.routes.url_helpers
def get_variant(version="high", disposition="attachment")
variant = file_variant(version)
return rails_representation_url(variant, only_path: true, disposition: disposition)
end
In my html, I can call my method with attachment disposition:
<a href="<%= #image.get_variant('high', 'attachment') %>" rel="example_group">
I can also download the image variant directly from my controller:
def download
redirect_to #image.get_variant('high', 'attachment')
end
If you want to only display the variant in the browser window, you can use 'inline':
redirect_to #image.get_variant('high', 'inline')
Not sure it's the best option, but it works.
I am currently building a rails app that uses the jquery-upload plugin to allows users to upload files to do things such as set their user avatar. If the upload is successful, it sets a hidden field on the form with the upload ID, and when the form is submitted, the association is saved. When I manually test this, it works the way it is supposed to. However, I cannot get my RSpec tests to pass.
I am using RSpec as my testing framework and Capybara-webkit as my javascript drive. The field where the file is supposed to attach looks like this
= file_field_tag :file, class: "upload_file_field"
(Also, using slim for templating)
The coffeescript that handles the file upload looks like this
$element.fileupload
dropZone: $dropzoneElement
url: "/uploads.json"
method: "PATCH"
fail: (e, data) =>
#showErrorOnFailure(e, data)
done: (e, data) =>
#onSuccessfulUpload(e, data)
Controller code that handles file uploads looks like this
class UploadsController < ApplicationController
def create
#upload = Upload.new(file: params[:file])
byebug
if #upload.save
respond_to do |format|
format.json { render json: {upload: #upload, url: #upload.file.url(:avatar) } }
end
else
respond_to do |format|
format.json { render json: {}, status: :unprocessable_entity }
end
end
end
end
And here is the RSpec code I am using in the test to attach the file
filepath = "#{Rails.root}/spec/support/fixtures/uploads/flickr.jpg"
attach_file :file, filepath
click_on "Submit"
expect(page).to have_css(".avatar-img img")
When I run the test, the entire request goes through (Capybara does not indicate it had trouble finding the file or the form field). However, the test fails. And when I use byebug to inspect the uploads controller at the point it receives the request to save a new upload, there are no parameters being sent. As in params[:file] evaluates to nil, when it should have the file information for flickr.jpg. Any idea why my file isn't attaching in the test, even though Capybara isn't raising any errors about it.
So after reading through this post I found an answer:
Capybara webkit doesn't pass params from angular
It looks like the problem came from the fact that I was using PATCH to send the uploads. After changing the method to PUT, my tests started passing.
When send_file is called, it's sending the file to the browser, but the browser is dumping the contents as plain-text on a new page instead of downloading the file. If I refresh that page, it then downloads the file as normal.
Route
get 'download' => 'qr_codes#download'
Controller
def download
path = Rails.root.join("events/active/#{params[:name]}/#{params[:batch]}/#{params[:file]}")
send_file(path, type: 'application/vnd.ms-excel', filename: params[:file])
end
View
<%= link_to 'Original Upload', download_path(name: #event_name,
batch: batch, file: batch_upload_filename(#event_name, batch)) %>
SOLUTION:
This ended up being a known issue with turbolinks. If using Turbolinks 5 like I am, the updated syntax is: data: { turbolinks: false }
This ended up being a known issue with turbolinks. If using Turbolinks 5 like I am, the updated syntax is:
data: { turbolinks: false }
Try setting the disposition:
def download
path = Rails.root.join("events/active/#{params[:name]}/#{params[:batch]}/#{params[:file]}")
send_file(path, type: 'application/vnd.ms-excel', filename: params[:file], disposition: 'attachment')
end
Or changing the file to ensure the extension is correct
"#{params[:file][0,params[:file].index(".")]}.xlsx"
Oh and don't inject params into a string to build routes for downloading. I can inject "../../" into :name, "config", into :batch, and "../config/database.yml" into :file. Add the file path to a model.
make helper method
def some_helper(content_type)
Rack::Mime::MIME_TYPES.invert[content_type].gsub(/\./mi, '')
end
and update link as
<%= link_to 'Original Upload', download_path(name: #event_name, batch: batch, file: batch_upload_filename(#event_name, batch, format: file_format(attachment.file.content_type))) %>
I have a rails app and stuck on a problem when trying to create a download link to some dynamic generated data.
I've placed a .to_pdf method in my Folha model. And on controller folhas_controller.rb:
def show
nome = "#{#folha.nome_do_mes}-#{#folha.ano}-#{DateTime.now.to_i}"
#folha = Folha.find(params[:id])
respond_to do |format|
format.pdf do
pdf = #folha.to_pdf(view_context)
send_data pdf.render, filename: "#{nome}.pdf", type: "application/pdf"
end
end
end
The issue is that the .to_pdf method is executed only the first time i click the link. For all other clicks it gives me the same file, no matter if my object was updated.
I dont know where in my stack this is ocurring.
It only happens in production. Im using Rails 3.2.6 on Thin 1.4.1 deployed to heroku.
Please help =)
I used a workaround, pretty sure its not the proper way:
routes.rb
resources :folhas do
resources :servicos
end
match 'exportar/:id/:dummy' => 'folhas#show', as: "exportar"
and then on the view:
<%= link_to image_tag('pdf_small.png'), exportar_path(id: folha.id, dummy: DateTime.now.to_i, format: 'pdf'), class: 'item' %>
that way a different link is placed each time the view is rendered.
Is there a way to make the users download the images attached using paperclip?
I just made a link like this:
link_to 'imagename', image.attachment.url
But this makes the browser open the image. I want the browser to ask the user to save the image. Is there a way to do that?
When it comes to sending a file you can find all information in here http://api.rubyonrails.org/classes/ActionController/Streaming.html There are most important cuts:
Simple download:
send_file '/path/to.zip'
Show a JPEG in the browser:
send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
Show a 404 page in the browser:
send_file '/path/to/404.html', :type => 'text/html; charset=utf-8', :status => 404
to use one of this option you have to create a new action in controller like this:
class SomeController < ApplicationController
def download_file
send_file image.attachment.path
end
end
Here's a simple solution using the HTML5 download attribute
<%= link_to image.name, image.attachment.url, download: image.attachment.original_filename %>