Convert images to PDF before uploading with Paperclip - ruby-on-rails

Using Paperclip for file upload in my Rails app and I need to convert images into separate PDFs before uploading to Amazon S3 servers. I know I can use Prawn for the image to PDF conversion and I can intercept the file using the answer to this stack overflow question
In the model:
has_attached_file :file
before_file_post_process :convert_images
...
def convert_images
if file_content_type == 'image/png' || file_content_type == 'image/jpeg'
original_file = file.queued_for_write[:original]
filename = original_file.path.to_s
pdf = Prawn::Document.new
pdf.image open(filename), :scale => 1.0, position: :center
file = pdf.render
end
end
However I'm unable to actually convert the image that is stored on S3. Any ideas what I'm missing?
Edit: Adding a save! call results in validations failing that weren't doing so before.

Was able to figure it out.
changed:
before_file_post_process :convert_images
to:
before_save :convert_images
and changed my convert_images method to:
def convert_images
if file_content_type == 'image/png' || file_content_type == 'image/jpeg'
file_path = file.queued_for_write[:original].path.to_s
temp_file_name = file_file_name.split('.')[0] + '.pdf'
pdf = Prawn::Document.new(:page_size => "LETTER", :page_layout => :portrait)
pdf.image File.open("#{file_path}"), :fit => [612, 792], position: :center
pdf.render_file temp_file_name
file_content_type = 'application/pdf'
self.file = File.open(temp_file_name)
File.delete(temp_file_name)
end
end

Related

Ruby on rails save base64 to xlsx (or pdf or word) and save it with paperclip

I have a base64 like this which I have generated on-line.It's for an xlsx file. I want to decode it and save it in db with paperclip so I did this :
decoded_data = Base64.decode64(Base64)
data = StringIO.new(decoded_data)
data.class_eval do
attr_accessor :content_type, :original_filename
end
data.content_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Model.create(file: data)
it creates a file and saves it on database but the file is damaged. I've tried it for image with image content type and it's fine but for pdf,word and xlsx it's not fine . Do you have any clue ?
Thanks in advance.
I've fixed the issue. The problem was for the content type.When I tried to store the files through rails_admin the file_content_type was :
for xlsx file content_type = "application/zip"
for csv file content_type = "text/plain"
for pdf file content_type = "application/pdf"
for word file content_type = "application/zip"
for image file content_type = "image"
But when I was trying to store the base64 file the content_type was quite different as you see below:
for xlsx file content_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
for csv file content_type = "text/plain"
for pdf file content_type = "application/pdf"
for word file content_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
for image file content_type = "image/jpg"
So I replaced that correct type and the problem soveld.
decoded_data = Base64.decode64(modified_base64)
data = StringIO.new(decoded_data)
data.class_eval do
attr_accessor :content_type, :original_filename
end
if params[:contentType] == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
#content_type = "application/zip"
elsif params[:contentType] == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
#content_type = "application/zip"
elsif params[:contentType] == "text/plain"
#content_type = "text/plain"
elsif params[:contentType] == "application/pdf"
#content_type = "application/pdf"
elsif params[:contentType].include?('image')
#content_type = "imgae"
end
data.content_type = #content_type
data.original_filename = params[:file_name]
And don't forget to set the file name, for example if the file is xlsx you can name it as sample.xlsx that's a big deal.

How to upload base64 image to s3 from rails controller?

I am making an ajax reject to my controller with some data and base64 image and now I want to upload this image to s3 and replace base64 with the image url. I am following this https://sebastiandobrincu.com/blog/how-to-upload-images-to-rails-api-using-s3
def split_base64(uri_str)
if uri_str.match(%r{^data:(.*?);(.*?),(.*)$})
uri = Hash.new
uri[:type] = $1 # "image/gif"
uri[:encoder] = $2 # "base64"
uri[:data] = $3 # data string
uri[:extension] = $1.split('/')[1] # "gif"
return uri
else
return nil
end
end
def convert_data_uri_to_upload(image_url)
image_data = split_base64(image_url)
image_data_string = image_data[:data]
image_data_binary = Base64.decode64(image_data_string)
temp_img_file = Tempfile.new("")
temp_img_file.binmode
temp_img_file << image_data_binary
temp_img_file.rewind
img_params = {:filename => "image.#{image_data[:extension]}", :type => image_data[:type], :tempfile => temp_img_file}
uploaded_file = ActionDispatch::Http::UploadedFile.new(img_params)
end
return uploaded_file
end
Now from my controller I am passing
convert_data_uri_to_upload(base64_image)
Now I don't know where to write the AWS credentials. According to the url I have to write the credentials in Fog.rb file but I don't have any such file. I have created one ImageUploader inside uploader folder which extends CarrierWave and wrote the configurations but it is also not working.
You can use dotenv ruby gem follow this : http://www.rubydoc.info/gems/dotenv-rails/2.1.1

Rails 5 Action Mailer - Prawn PDF wrong number of arguments

I have set prawn in my rails app to generate:
format.pdf do
pdf = SalesByDayPdf.new(#daily_salesnp, #amount_total, #discount_total, #grand_total)
pdf.render_file "daily_sales.pdf"
send_data pdf.render, filename: 'daily_sales.pdf', type: 'application/pdf', disposition: 'inline'
end
And this is my SalesByDayPdf
def initialize(daily_salesnp, grand_total, discount_total, amount_total)
super()
#daily_salesnp = daily_salesnp
#amount_total = amount_total
#discount_total = discount_total
#grand_total = grand_total
header
text_content
table_content
footer
end
This works fine.
Now I want to send this pdf from action mailer. I have set it in my DailySalesMailer as:
def send_daily_sale(daily_salesnp, grand_total, discount_total, amount_total)
#daily_salesnp = daily_salesnp
#amount_total = amount_total
#discount_total = discount_total
#grand_total = grand_total
attachments["daily_sales.pdf"] = SalesByDayPdf.new(daily_salesnp, grand_total, discount_total, amount_total)
mail(:to => "email#gmail.com", :subject => 'Sales by Day Report')
end
So basically I copied the pdf generator in mailer and passed same arguments defined in my controller.
But I'm getting:
wrong number of arguments (given 1, expected 4)
What am I doing wrong?
The solution is to modify the attachment to:
attachments["daily_sales.pdf"] = SalesByDayPdf.new(daily_salesnp, grand_total, discount_total, amount_total).render

How to add text to image?

I am trying to add text on my image with RMagick. This is my code:
version :thumb do
process :resize_to_limit => [400, 300]
process :addt
end
def addt
manipulate! do |img|
title = Magick::Draw.new
img = title.annotate(img, 0,0,0,40, 'test') {
self.font_family = 'Helvetica'
self.fill = 'white'
self.stroke = 'transparent'
self.pointsize = 32
self.font_weight = Magick::BoldWeight
self.gravity = Magick::CenterGravity
}
end
end
The problem with this code is that it totally blocks my application. I can't open any other part of my site and can't turn off my server process. I need to kill server process completely to start the application again.
What could be a problem?
just try this, i cant solve your code . but hope this one can help you with that.
1st install this gem
Source: https://github.com/rmagick/rmagick
next
To start playing with RMagick, you can stick this in one of your controllers:
require ‘RMagick’
include Magick
def addt
img = ImageList.new(‘Your image path eg.public/computer-cat.jpg’)
txt = Draw.new
img.annotate(txt, 0,0,0,0, “The text you want to add in the image”){
txt.gravity = Magick::SouthGravity
txt.pointsize = 25
txt.stroke = ‘#000000′
txt.fill = ‘#ffffff’
txt.font_weight = Magick::BoldWeight
}
img.format = ‘jpeg’
send_data img.to_blob, :stream => ‘false’, :filename => ‘test.jpg’, :type => ‘image/jpeg’, :disposition => ‘inline’
end
hope this one help you..
if you cant understand ..click this http://mikewilliamson.wordpress.com/2010/04/29/adding-text-to-pictures-with-rmagick-and-rails/

Paperclip processor generate image from other style

I try find way write Paperclip processor which generate image based on other style.
I need generate style with size "54x54" and then generate another style with size 120x120 based on "54x54" style (background + small image).
Model:
class Medal < ActiveRecord::Base
has_attached_file :icon,
styles: {
:'48' => ['48', :png],
:'54' => ['54', :png],
:'120' => ['120', :png],
:'fb' => { geometry: '120', format: :png, processors: [ :fb_medal_icon ] },
}
end
Processor:
module Paperclip
class FbMedalIcon < Processor
def initialize(file, options = {}, attachment = nil)
super
#whiny = options[:whiny].nil? ? true : options[:whiny]
#format = File.extname(#file.path)
#basename = File.basename(#file.path, #format)
end
def make
src = #file
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
begin
arguments = '-gravity center :icon :background :dest'
options = {
icon: icon_path,
background: "#{File.expand_path(src.path)}[0]",
dest: File.expand_path(dst.path)
}
composite(arguments, options)
rescue Cocaine::ExitStatusError
raise Paperclip::Error, "There was an error processing the icon for #{#basename}" if #whiny
rescue Cocaine::CommandNotFoundError
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `composite` command. Please install ImageMagick.")
end
dst
end
def composite(arguments = "", local_options = {})
Paperclip.run('composite', arguments, local_options)
end
private
def icon_path
style = :'54'
icon = #attachment.instance.icon
if icon.queued_for_write[style].present?
icon.queued_for_write[style].path
else
Paperclip.io_adapters.for(icon.styles[style]).path
end
end
end
end
But I get error "NoMethodError: undefined method `path' for nil:NilClass"
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:174:in `staged_path'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:25:in `copy_to_tempfile'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:19:in `cache_current_values'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:11:in `initialize'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/registry.rb:31:in `new'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/registry.rb:31:in `for'
from /my_projects/MyApp/lib/paperclip_processors/fb_medal_icon.rb:63:in `icon_path'
from /my_projects/MyApp/lib/paperclip_processors/fb_medal_icon.rb:24:in `make'
Any idea how right handle this case?
You've not mentioned why you've used your own processor, but I'd highly recommend using ImageMagick to handle the styling
If you install ImageMagick (it can be a problem on Windows), you'll be able to get your styles without using the custom processor. I have code if you'd like to see

Resources