I have code to write a file to save a PDF and then upload it to s3. What I have works perfectly in dev. but not in production.
def upload_to_s3(pdf)
save_path = "#{Rails.root}/tmp/pdfs/invoice_#{#invoice.id}.pdf"
f = File.new(save_path, 'w:ASCII-8BIT')
f.write(pdf)
uploader = InvoiceUploader.new
File.open(save_path) { |file| uploader.store!(file) }
#invoice.update(pdf: uploader.url)
File.delete(save_path)
uploader.url
end
Stack Trace:
Rendered invoices/pdf.html.erb (6.5ms)
Completed 500 Internal Server Error in 1420ms (ActiveRecord: 34.6ms)
Errno::ENOENT (No such file or directory # rb_sysopen - /home/deploy/reputation/releases/20180401031049/tmp/pdfs/invoice_2.pdf):
app/controllers/api/v1/invoices_controller.rb:140:in `initialize'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:140:in `new'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:140:in `upload_to_s3'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:65:in `pdf'
The error message clearly states:
Errno::ENOENT (No such file or directory # rb_sysopen - /home/deploy/reputation/releases/20180401031049/tmp/pdfs/invoice_2.pdf): ...
Create the directory /home/deploy/reputation/releases/20180401031049/tmp/pdfs/ in production upfront. Since it’s dynamic (dependent on the release datetime,) it’s better to create it in your ruby code:
save_dir = "#{Rails.root}/tmp/pdfs/"
Dir.mkdir(save_dir)
save_path = ...
Related
I have a model called client_billing_file where I use Carrierwave to upload a CSV file like this:
mount_uploader :billing_file_name, UsageFileUploader
and I schedule a job to run 5 minutes after commiting the creation of a new record:
after_commit :generate_usage_file, on: :create
def generate_usage_file
Resque.enqueue_in(5.minutes, GenerateUsageFileQueue, id, admin.email)
end
This is my background job:
def self.perform(client_billing_file_id, email)
cbf = ClientBillingFile.find(client_billing_file_id)
filepath = cbf.billing_file_name.current_path
csv_file = CSV.read(filepath, headers: true)
.
.
.
end
This is working in my development and testing environments, but it fails when I try to open the CSV file in the staging environment (where it actually uploads the file to the S3 bucket). I checked the bucket and the file is getting uploaded to the specified directory correctly, but for some reason the job is throwing the following error:
Exception Errno::ENOENT
Error No such file or directory # rb_sysopen - my_path/my_file.csv
Versions:
Ruby 2.6.6
Rails 4.2.11
Carrierwave 0.8.0
Fog 1.38.0
I tried Jared Beck's idea and it's working now, basically I added this condition to my BG job:
if Rails.env.production? || Rails.env.staging?
url = cbf.billing_file_name.url
cbf.billing_file_name.download!(url)
end
So the final code looks like this:
def self.perform(client_billing_file_id, email)
cbf = ClientBillingFile.find(client_billing_file_id)
if Rails.env.production? || Rails.env.staging?
url = cbf.billing_file_name.url
cbf.billing_file_name.download!(url)
end
filepath = cbf.billing_file_name.current_path
csv_file = CSV.read(filepath, headers: true)
.
.
.
end
I'm currently working on a Rails 5.2 application using the combine pdf gem. I'm trying to merge two PDF files but somehow I'm unable to load files from the public directory.
In the controller I have the following method:
def pdf_download
pdf = CombinePDF.new
pdf << CombinePDF.load("#{Rails.root}/public/pdfs/1.pdf")
pdf << CombinePDF.load("#{Rails.root}/public/pdfs/1.pdf")
pdf.save "combined.pdf"
send_data combined_file.to_pdf, filename: "combined.pdf", type: "application/pdf"
end
I have tried many posts on StackOverflow without success such as using Rails.root. But I still get the same error:
Errno::ENOENT (No such file or directory # rb_sysopen - app/public/pdfs/1.pdf):
Is there any additional configuration I have to do to load files from public? and if these PDF shouldn't be in public where should I store them?
This fixed it for me:
def pdf_download
pdf = CombinePDF.new
pdf << CombinePDF.load(Rails.root.join("public", "pdfs/1.pdf").to_s)
pdf << CombinePDF.load(Rails.root.join("public", "pdfs/2.pdf").to_s)
# pdf.save "combined.pdf"
send_data pdf.to_pdf, filename: "combined.pdf", type: "application/pdf"
end
This fixed it for me:
pdf << CombinePDF.load("./public/pdfs/1.pdf")
I try to modify paperclip image from my model after a server change.
I have a file with id of my model and name of image like that
3;3da442247510f15c07fead8f41cd1c9441694b02.jpg
4;e3b652bfe16759002d6dd3da608475069df1c02e.jpg
5;0699ab4040c4d4f6e8ec390170014661bc5f6d96.jpg
I have write a script to find the file and give ti to my model
File.open("titi.txt", "r") do |f|
f.each_line do |line|
tab=line.split(";")
puts "id => #{tab[0]} | nom => #{tab[1]}"
c=Contact.find(tab[0])
file = File.open("#{Rails.root}/public/system/contact/#{tab[1]}")
c.photo = file
file.close
c.save!
end
end
I launch my script like that
RAILS_ENV=production rails runner script.rb
But I have this error
script.rb:6:in `initialize': No such file or directory # rb_sysopen - /var/www/contactmedia/public/system/contact/3da442247510f15c07fead8f41cd1c9441694b02.jpg (Errno::ENOENT)
but when I do
ls -la /var/www/contactmedia/public/system/contact/3da442247510f15c07fead8f41cd1c9441694b02.jpg
I have a file....
What is wrong in my script ? Whant can I test to move my images.
Thanks
EDIT
it's OK i have found why I read a windows file so i have a \r at end of line. I read my file like that now
file = File.open("#{Rails.root}/public/system/contact/#{tab[1].chomp}")
if I load the file in my app on Heroku, everything works, but when I tried again to reload the application, it gives me the following error:
2013-01-25T08:48:31+00:00 app[web.1]: app/controllers/main_controller.rb:20:in `index'
2013-01-25T08:48:31+00:00 app[web.1]:
2013-01-25T08:48:31+00:00 app[web.1]:
2013-01-25T08:48:31+00:00 app[web.1]: Errno::ENOENT (No such file or directory - /app/config/cases/casesID6.yml):
2013-01-25T08:48:31+00:00 app[web.1]: app/controllers/main_controller.rb:20:in `read'
LOCALLY IT WORK FINE !
main controller:
# importo yaml di configurazione
require 'yaml'
if Survey.exists?(1)
#idOfSurvey = Survey.find {|s| s['active_state'] == true}['id']
nameOfSurvey = "casesID"+String(#idOfSurvey)+".yml"
#survey = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config/cases', nameOfSurvey))).result)
else
render :action => 'noYaml' and return
end
upload controller :
#inserisco il nuovo questionario
survey = Survey.new
if Survey.exists?(1)
n = String(Integer(Survey.maximum("Id"))+1)
survey.name = "casesID#{n}"
else
survey.name = "casesID1"
end
File.open(Rails.root.join('config/cases', survey.name+".yml"), 'wb+') do |file|
file.write(uploaded_io.read)
end
survey.save()
I believe that my file uploaded to Heroku, may be cleared by the platform for issues of memory, for example, or because it saves them as temporary, is this possible? solutions!
I repeat, everything works fine locally :(
Whilst you can write to the Heroku filesystem once you scale, restart or push a new version of your code then the file will be gone.
You need to use a persistant file store such as Amazon S3, Rackspace or such like - read more at https://devcenter.heroku.com/articles/dynos#ephemeral-filesystem and use a gem like CarrierWave or Paperclip which make connecting to S3 super simple.
I am attempting to code a very simple way for a user to add html files to my Heroku app. These files would be saved in ./log for rendering later. I have tested my code locally (in both development and production), but when I attempt to upload a file on my Heroku hosted repo I get internal server error 500.
controller upload.rb:
class UploadController < ApplicationController
def index
render :file => 'upload/uploadfile.haml'
end
def uploadFile
file_param = params[:upload][:datafile]
post = DataFile.save(file_param)
render :text => "File has been uploaded successfully"
end
end
model data_file.rb:
class DataFile < ActiveRecord::Base
def self.save(upload)
# Changed Default Destination: [__RAILS_DIR__/log]
name = "./log/" + upload.original_filename
# can haz data directory?
require 'FileUtils'
FileUtils.mkdir_p(File.dirname(name))
File.open(name, "wb") { |f| f.write(upload.read) }
end
end
view uploadfile.haml:
%h1 File Upload
= form_for :upload,:url=>{:action => 'uploadFile'},:html => { :multipart => true } do |f|
%p
%label{:for => "upload_file"} Select File
\:
\#{f.file_field 'datafile'}
= f.submit "Upload"
heroku logs:
2012-08-07T14:13:20+00:00 app[web.1]: Started POST "/uploadFile" for 69.29.117.99 at 2012-08-07 14:13:20 +0000
2012-08-07T14:13:20+00:00 app[web.1]: Processing by UploadController#uploadFile as HTML
2012-08-07T14:13:20+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"1dAXkMulNR0d8S/l6QC8JnpSDtNBaHoyKJezgnheR10=", "upload"=>{"datafile"=>#>}, "commit"=>"Upload"}
2012-08-07T14:13:20+00:00 app[web.1]: Completed 500 Internal Server Error in 3ms
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]: LoadError (no such file to load -- FileUtils):
2012-08-07T14:13:20+00:00 app[web.1]: app/models/data_file.rb:7:in save'
2012-08-07T14:13:20+00:00 app[web.1]: app/controllers/upload_controller.rb:8:inuploadFile'
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]: cache: [POST /uploadFile] invalidate, pass
heroku: http://upload-example.herokuapp.com/
github: https://github.com/halterj1/upload
Please no trying to convince me to use paperclip or carrierwave, that does not answer my question. Any help would be greatly appreciated, thanks in advance guys!
You should read this article on heroku: https://devcenter.heroku.com/articles/read-only-filesystem
edit:
As stated in article.
Your app is compiled into a slug for fast distribution across the dyno manifold. The filesystem for the slug is read-only, which means you cannot dynamically write to the filesystem for semi-permanent storage. The following types of behaviors are not supported:
Caching pages in the public directory
Saving uploaded assets to local disk (e.g. with attachment_fu or paperclip)
Writing full-text indexes with Ferret
Writing to a filesystem database like SQLite or GDBM
Accessing a git repo for an app like git-wiki
There are two directories that are writeable: ./tmp and ./log (under your application root). If you wish to drop a file temporarily for the duration of the request, you can write to a filename like #{RAILS_ROOT}/tmp/myfile_#{Process.pid}. There is no guarantee that this file will be there on subsequent requests (although it might be), so this should not be used for any kind of permanent storage.