Upload base64 encoded image with paperclip - Rails - ruby-on-rails

Using cropit I get the image bas64 encode on rails through params.
image = params['image'].gsub('data:image/jpeg;base64,', '')
decoded_file = Base64.decode64(image)
and then I save to amazon s3 with paperclip
begin
file = Tempfile.new(['image', '.jpg'])
file.binmode
file.write decoded_file
unless params['image_id']
media_img = Media::Image.new()
media_img.image = file
if media_img.save
render json: {status: 'success'}
else
render json: {status: 'error'}
end
else
img = Media::Image.find(params['image_id'])
img.update_attribute(:image, file)
img.update_attribute(:name, params['image_name'])
render json: {status: 'success'}
end
file.close
ensure
file.unlink
end
The main problem is that the code is working only for jpeg images because I use gsub only for data:image/jpeg;base64, and when creating the Tempfile I created jpg Tempfile.new(['image', '.jpg']) . So how can I handle with best practice jpg, jpeg and png?

This is my solution, using Paperclip.io_adapters.for(image) where image is base64 string.
def create_image image, image_name, cat
signature = Paperclip.io_adapters.for(image)
base_name = File.basename(image_name,File.extname(image_name))
signature.original_filename = "#{base_name}.jpg"
media_img = Media::Image.new()
media_img.image = signature
media_img.company_id = current_company_id
media_img.type = cat
media_img.save
end

Related

how to read a file from blob and save it to public folder in rails

i am reading a pdf file from blob and saving it to local folder
#doc = Document.find(params[:id])
blob = #doc.docs.first.blob
ActiveStorage::Downloader.new(blob.service).open(blob.key, checksum: blob.checksum) do |tempFile|
temppdf = Tempfile.new ["mypdf", ".pdf"]
pathpdf = "app/assets/images/" + current_account.email+'.pdf'
tempFile.save(pathpdf)
end
You can use ActiveStorage::Blob#open to steam the file directly to disk circumventing the tempfile:
#doc = Document.find(params[:id])
blob = #doc.docs.first.blob
# app/assets certainly isn't a public path...
fn = Rails.root.join('public', 'uploads', 'mypdf.pdf')
File.open(fn, "wb+") do |file|
blob.download { |chunk| file.write(chunk) }
end

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

Convert images to PDF before uploading with Paperclip

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

Rails form to upload a file to directory - undefined method

I'm trying to create a form that uploads a pdf and an image to a directory. I currently have this code, which i've copied off a working example:
def resources_addprocess
r = Resource.new
r.title = params[:title]
r.reference = params[:reference]
r.description = params[:description]
r.campaign = params[:campaign]
r.resourcetype = params[:resourcetype]
uploaded_io = params[:file]
File.open(Rails.root.join('public','resources', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
end
if params[:preview].present?
uploaded_io2 = params[:preview]
File.open(Rails.root.join('app','assets','images','preview', 'resources', uploaded_io2.original_filename), 'wb') do |file|
file.write(uploaded_io2.read)
end
r.preview = uploaded_io2.original_filename
end
r.file = uploaded_io.original_filename
if r.save
flash[:success] = "You successfully added a resource."
redirect_to "/cms/resources"
else
flash[:error] = "resource wasn't successfully."
redirect_to "/cms/resources"
end
end
But I get the following error: undefined method 'original_filename' This worked on a different project.. not sure why it isn't now?
Found the answer just after posting this,
Turns out if you use the =form_tag you need to define it's multipart..
http://guides.rubyonrails.org/form_helpers.html#uploading-files

Resources