Cant send a business_card.png to abbyy with ROR - ruby-on-rails

I am just tryout some new technologies and find out about abbyy gem I created a free account on http://ocrsdk.com/plans-and-pricing/
I am following the instruction on the gem
class Client < ActiveRecord::Base
def abbyy
client = Abbyy::Client.new
client.process_business_card self.business_card, exportFormat: 'xml', imageSource: 'photo'
# Errno::ENOENT: No such file or directory - https://appname-dev.s3.amazonaws.com/uploads/client/business_card/1/bizcard.jpg
client.get_task_status
client.get
end
end
but I am getting a this error
Errno::ENOENT: No such file or directory - https://appname-dev.s3.amazonaws.com/uploads/client/business_card/1/bizcard.jpg
I made sure that the directory I am uploading is public
here is a link to a demo app https://github.com/mzaragoza/abbyy

Add require 'open-uri' to the top of your file.
Then download the file, and only then give it to abby:
def abby
require 'tempfile'
card = Tempfile.new('business_card')
card.binmode
stream = open(self.business_card.url)
card.write(stream.read)
stream.close
card.close
client = Abbyy::Client.new
client.process_business_card card.path, exportFormat: 'xml', imageSource: 'photo'
client.get_task_status
client.get
ensure
# ensuring every handle is closed, and ignoring exceptions, which could arise if handles already closed
# or haven't been opened
stream.close rescue nil
card.close rescue nil
card.unlink rescue nil
end

Related

IO.copy_stream is not copying file which is read from S3

I have a model Report to export all the Pdf attachments done for the bills. I have other models Bill, Upload.
Bill has many uploads
Tech Stack used
Ruby 2.5.8
Rails 5.0.7
Dummy Code
require 'fileutils'
require 'zip'
require 'open-uri'
class Report < ApplicationRecord
main_dir = "tmp/Attachment-#{self.id}"
FileUtils::mkdir_p main_dir
bills.each do |bill|
bill_directory_name = 'Bill_#{bill.id}'
bill.uploads.each do |bill_upload|
begin
FileUtils::cd main_dir do
FileUtils::mkdir_p "#{bill_directory_name}"
file = open(bill_upload.file.url, 'rb')
upload_name = "Invoice-#{bill_upload.file_file_name}-#{bill_upload.id}"
FileUtils::cd "#{bill_directory_name}" do
IO.copy_stream(file, "#{upload_name}")
end
end
rescue => exp
Airbrake.notify(exp)
end
end
end
path = "tmp/Attachment-#{self.id}"
archive = File.join(path, "Attachment-#{self.id}" + '.zip')
FileUtils.rm archive, force: true
Zip::File::open(archive, 'w') do |zipfile|
Dir["#{path}/**/**"].reject{|f| f==archive }.each do |file|
zipfile.add(file.sub(path + '/', ''), file)
end
end
end
Zip folder is created successfully. When I extract zip folder, I can see there are many sub folders created for bills. Each bill folder have uploaded PDF files as well and it's working.
Problem
Most of the time exported bill sub-directory contains PDF uploaded file. But, rarely sometime (once in a 100's of iteration), when I export report, I cannot see PDF file inside some of the bill sub directory. I have added error handling but there is no error generated. So, it's hard to reproduce this issue at my end.
How to confirm that this file copy command is successful IO.copy_stream()?
Please check dummy code and provide your feedback if I need to improve or modify any line of code?
file = open(bill_upload.file.url, 'rb') # File is read from S3
upload_name = "Invoice-#{bill_upload.file_file_name}-#{bill_upload.id}"
FileUtils::cd "#{bill_directory_name}" do
IO.copy_stream(file, "#{upload_name}")
end
Any help would be appreciated.

Download an active Storage attachment to disc

The guide says that I can save an attachment to disc to run a process on it like this:
message.video.open do |file|
system '/path/to/virus/scanner', file.path
# ...
end
My model has an attachment defined as:
has_one_attached :zip
And then in the model I have defined:
def process_zip
zip.open do |file|
# process the zip file
end
end
However I am getting an error :
private method `open' called
on the zip.open call.
How can I save the zip locally for processing?
As an alternative in Rails 5.2 you can do this:
def process_zip
# Download the zip file in temp dir
zip_path = "#{Dir.tmpdir}/#{zip.filename}"
File.open(zip_path, 'wb') do |file|
file.write(zip.download)
end
Zip::File.open(zip_path) do |zip_file|
# process the zip file
# ...
puts "processing file #{zip_file}"
end
end
That’s an edge guide (note edgeguides.rubyonrails.org in the URL); it applies to the master branch of the rails/rails repository on GitHub. The latest changes in master haven’t been included in a released version of Rails yet.
You’re likely using Rails 5.2. Use edge Rails to take advantage of ActiveStorage::Blob#open:
gem "rails", github: "rails/rails"

Download all files to a zip within Heroku

I've been knocking my head around with Heroku, while trying to download a zip file with all my receipt files data.
The files are stored on amazon s3 and it all works fine on my development machine..
I thought it had to do with Tempfile, and abandoned that previous solution, since heroku has some strict policies with their filesystem, so i used the tmp folder, but the problem doesn't seem to be there. I already tried to load directly from s3 (using openUri) to the zip file, but it doesn't seem to work either on Heroku.
What might be wrong with my code for Heroku not loading the files to the zip?
Here is my model method :
def zip_receipts(search_hash=nil)
require 'zip/zip'
require 'zip/zipfilesystem'
t=File.open("#{Rails.root}/tmp/#{Digest::MD5.hexdigest(rand(12).to_s)}_#{Process.pid}",'w')
# t = Tempfile.new(Digest::MD5.hexdigest(rand(12).to_s))
# Give the path of the temp file to the zip outputstream, it won't try to open it as an archive.
Zip::ZipOutputStream.open(t.path) do |zos|
logger.debug("search hash Zip: #{search_hash.inspect}")
self.feed(search_hash).each do |receipt|
begin
require 'open-uri'
require 'tempfile'
#configures filename
filen = File.basename(receipt.receipt_file_file_name)
ext= File.extname(filen)
filen_noext = File.basename(receipt.receipt_file_file_name, '.*')
filen=filen_noext+SecureRandom.hex(10)+ext
logger.info("Info Zip - Filename: #{filen}")
# Create a new entry on the zip file
zos.put_next_entry(filen)
# logger.info("Info Zip - Added entry: #{zos.inspect}")
# Add the contents of the file, reading directly from amazon
tfilepath= "#{Rails.root}/tmp/#{File.basename(filen,ext)}_#{Process.pid}"
open(tfilepath,"wb") do |file|
file << open(receipt.authenticated_url(:original),:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE).read
end
zos.print IO.binread tfilepath
# logger.info("Info Zip - Extracted from amazon: #{zos.inspect}")
rescue Exception => e
logger.info("exception #{e}")
end # closes the exception begin
end #closes receipts cycle
end #closes zip file stream cycle
# The temp file will be deleted some time...
t.close
#returns the path for send file controller to act
t.path
end
My controller:
def download_all
#user = User.find_by_id(params[:user_id])
filepath = #user.zip_receipts
# Send it using the right mime type, with a download window and some nice file name.
send_file(filepath,type: 'application/zip', disposition: 'attachment',filename:"MyReceipts.zip")
end
And I write also my view and routes, so that it might serve anyone else trying to implement a download all feature
routes.rb
resources :users do
post 'download_all'
end
my view
<%= link_to "Download receipts", user_download_all_path(user_id:user.id), method: :post %>
The problem seemed to be with the search hash, and the sql query, and not the code itself. For some reason, the receipts get listed, but aren't downloaded. So it is an all different issue
In the end i have this code for the model
def zip_receipts(search_hash=nil)
require 'zip/zip'
require 'zip/zipfilesystem'
t=File.open("#{Rails.root}/tmp/MyReceipts.zip_#{Process.pid}","w")
# t = Tempfile.new(Digest::MD5.hexdigest(rand(12).to_s))
#"#{Rails.root}/tmp/RecibosOnline#{SecureRandom.hex(10)}.zip"
puts "Zip- Receipts About to enter"
# Give the path of the temp file to the zip outputstream, it won't try to open it as an archive.
Zip::ZipOutputStream.open(t.path) do |zos|
self.feed(search_hash).each do |receipt|
begin
require 'open-uri'
require 'tempfile'
filen = File.basename(receipt.receipt_file_file_name)
ext= File.extname(filen)
filen_noext = File.basename(receipt.receipt_file_file_name, '.*')
filen=filen_noext+SecureRandom.hex(10)+ext
# puts "Info Zip - Filename: #{filen}"
# Create a new entry on the zip file
zos.put_next_entry(filen)
zos.print open(receipt.authenticated_url(:original),:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE).read
rescue Exception => e
puts "exception #{e}"
end # closes the exception begin
end #closes receipts cycle
end #closes zip file stream cycle
# The temp file will be deleted some time...
t.close
#returns the path for send file controller to act
t.path
end

CarrierWave with custom processor not registering

I am using carrierwave to upload a video then have a version called thumb with a custom processor that takes the video and creates a screenshot using streamio-ffmpeg. Both the video and the file are uploaded correctly but when calling uploader.url(:thumb) I get:
ArgumentError: Version thumb doesn't exist!
VideoUploader.rb
require 'carrierwave/processing/mime_types'
require 'streamio-ffmpeg'
class VideoUploader < CarrierWave::Uploader::Base
include CarrierWave::VideoConverter
include CarrierWave::MimeTypes
process :set_content_type
storage :file
version :thumb do
process :create_thumb
#def full_filename(for_file)
# "thumb_#{File.basename(for_file, File.extname(for_file))}.png"
#end
end
def create_thumb
cached_stored_file! if !cached?
movie = FFMPEG::Movie.new(current_path)
dirname = File.dirname(current_path)
thumb_path = "#{File.join(dirname, File.basename(path, File.extname(path)))}.png"
movie.screenshot(thumb_path, :seek_time => 5)
File.rename thumb_path, current_path
end
def file_identifier
model[:video]
end
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
return "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.user_id}/#{model.id}"
end
end
Then model.video_url(:thumb) returns the argument error. I am not sure what to do or why the version isn't registered any help would be great, thanks.
Fix
What contributed to the error was a mix of restarting the server but not restarting the rails console. Once i did this the Argument error went away but I was getting the wrong path. So i uncommented
def full_filename(for_file)
"thumb_#{File.basename(for_file, File.extname(for_file))}.png"
end
and used
[model].video.recreate_versions!
to correct any errors in the paths or naming schemes that could have occured
most likely some step in your create_thumb method is failing and thus the thumb is never created and has no URL. Are there any exceptions being thrown to your logs?
Perhaps you need to specify the FFMPEG binary location:
FFMPEG.ffmpeg_binary = '/usr/local/bin/ffmpeg'

How to open file that is stored by CarrierWave in GridFs from a rails model? (File.open issue)

I'm using CarrierWave to store files in gridfs, but having problems with opening them from my model.
Here are my configs:
/config/initialize/carrierwave.rb
CarrierWave.configure do |config|
config.grid_fs_database = Mongoid.database.name
config.grid_fs_host = Mongoid.config.master.connection.host
config.storage = :grid_fs
config.grid_fs_access_url = "/files"
end
/app/controllers/gridfs_controller.rb
/require 'mongo'
class GridfsController < ActionController::Metal
def serve
gridfs_path = env["PATH_INFO"].gsub("/files/", "")
begin
gridfs_file = Mongo::GridFileSystem.new(Mongoid.database).open(gridfs_path, 'r')
self.response_body = gridfs_file.read
self.content_type = gridfs_file.content_type
rescue
self.status = :file_not_found
self.content_type = 'text/plain'
self.response_body = ''
end
end
end
/app/uploaders/list_uploader.rb
class ListUploader < CarrierWave::Uploader::Base
storage :grid_fs
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
and in routes
match "/files/uploads/*path" => "gridfs#serve"
So, I have a model, which have a text file
class Campaign
include Mongoid::Document
mount_uploader :list, ListUploader
When I'm calling something like <%=link_to "List", #campaign.list.url %> from my view, it opens fine. But when I'm trying something like File.open("#{campaign.list.url}", "r") from campaign model, it fails. It gives me false even when I'm calling File.exists?("/files/uploads/campaign/list/4eb02c4d6b1c0f02b200000b/list.txt"), which is a proper url for that file. So, the question is how should I call it, to open the file from model? And for some reasons, it is important to open it from model. Any suggestions would help, thank you.
Carrierwave url with mongodb gridfs is not a physical path. Its merely a logical route to download the file from gridfs. Thats why you cannot access it from ruby File.open. Check out the below snippet from rails console trying to open the file from gridfs
File.open(User.first.image.pic.url,'r')
Errno::ENOENT: No such file or directory - /images/uploads/e5a1007d34.jpg
see it throw No such file or directory., So you have to download a file instead opening by
>> require 'open-uri'
>> open('image.jpg', 'wb') do |file|
?> file << open('http://0.0.0.0:3000' + (User.first.image.pic.url)).read
>> p file
>> end
#<File:image.jpg>
=> #<File:image.png (closed)>

Resources