I'm trying to upload a file to an email as attachment.When i try to upload, i have an error
"undefined method `original_filename' for nil:NilClass" What i'm doing wrong?
I need to catch the file from the controller,and handle the exception if params[:file] not present?
In my view, there's simple upload file tag
%strong Send Email with PDF attachment:
= file_field_tag :file
I need to catch the file from the controller,
This is my controller..
#name = params[:file].original_filename
if params[:file].present?
directory = "public/data"
path = File.join(directory, #name)
uniq_name = (0...10).map {(65 + rand(26)).chr}.join
time_footprint = Time.now.to_formatted_s(:number)
File.open(path, "wb") do |file|
file.write(params[:file].read)
#uniq_path = File.join(directory, uniq_name + time_footprint + File.extname(file))
File.rename(file, #uniq_path)
end
else
flash[:notice] = "You are going to send email without the invoice"
redirect_to update_estimate_job_final_invoices_path(#ticket)
end
The first line is #name = params[:file].original_filename. If params[:file] is not present then the call to original_filename will fail. Move that line inside the if statement:
if params[:file].present?
#name = params[:file].original_filename
directory = "public/data"
path = File.join(directory, #name)
...
else
...
end
Related
I saw a bunch of question with a similar topic but I couldn't find a solution to my problem. Hopefully someone can help.
I have a Ruby on Rails app. In this app, I have some base64 data that I want to decode and write in a file. When I have a small script that I call through ruby myFile.rb, the program behaves as expeted. However when I run the same code with rails c. I have the following error:
Traceback (most recent call last):
7: from (irb):1:in `<main>'
6: from app/models/node.rb:1:in `<main>'
5: from app/models/node_manager.rb:317:in `<main>'
4: from app/models/node_manager.rb:255:in `convert_base64_to_file'
3: from app/models/node_manager.rb:255:in `open'
2: from app/models/node_manager.rb:255:in `block in convert_base64_to_file'
1: from app/models/node_manager.rb:255:in `write'
Encoding::UndefinedConversionError ("\xF8" from ASCII-8BIT to UTF-8)
Here are my files:
class I wrote in node_manager.rb
class NodeManager
class MacaroonInterceptor < GRPC::ClientInterceptor
attr_reader :macaroon
def initialize(macaroon)
#macaroon = macaroon
super
end
def request_response(request:, call:, method:, metadata:)
metadata['macaroon'] = macaroon
yield
end
def server_streamer(request:, call:, method:, metadata:)
metadata['macaroon'] = macaroon
yield
end
end
def initialize(tls_path, macaroon_path, node_ip)
#tls_path = tls_path
#macaroon_path = macaroon_path
#node_ip = node_ip
#node = connect(#tls_path, #macaroon_path, #node_ip)
end
def connect(tls_path, macaroon_path, node_ip)
certificate = File.read(File.expand_path(tls_path))
credentials = GRPC::Core::ChannelCredentials.new(certificate)
macaroon_binary = File.read(File.expand_path(macaroon_path))
macaroon = macaroon_binary.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join
if stub = Lnrpc::Lightning::Stub.new(
node_ip,
credentials,
interceptors: [NodeManager::MacaroonInterceptor.new(macaroon)],
channel_args: {"grpc.max_receive_message_length" => 1024 * 1024 * 50}
)
return stub
else
puts 'error'
raise "Could not connect to the node"
end
end
def get_info()
begin
node_info = #node.get_info(Lnrpc::GetInfoRequest.new())
raise LoadError if !node_info
return #node.get_info(Lnrpc::GetInfoRequest.new())
rescue
puts "could not connect to the node"
end
end
# Class methods
def self.convert_base64_to_file(directory: nil, file_name:, base64data:)
if directory
file_path = [directory, file_name].join('/')
else
file_path = file_name
end
file = File.open("file_name", 'w') {|f| f.write(Base64.decode64(base64data)) }
return file_path
end
end
script I run - works when I call ruby node_manager.rb and not when I run it with rails c
admin_tls_base64 = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNKekNDQWMyZ0F3SUJBZ0lSQUlWYzdlNHkxVGlpcHpmNWtHd09BUkF3Q2dZSUtvWkl6ajBFQXdJd01URWYKTUIwR0ExVUVDaE1XYkc1a0lHRjFkRzluWlc1bGNtRjBaV1FnWTJWeWRERU9NQXdHQTFVRUF4TUZZV3hwWTJVdwpIaGNOTWpFd056QTRNVEF5TmpFMFdoY05Nakl3T1RBeU1UQXlOakUwV2pBeE1SOHdIUVlEVlFRS0V4WnNibVFnCllYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1RNHdEQVlEVlFRREV3VmhiR2xqWlRCWk1CTUdCeXFHU000OUFnRUcKQ0NxR1NNNDlBd0VIQTBJQUJMQ3B2eDdZb1ptZURIQVdjN0ozdmZTTUhPNEJhRnpMV0hJUXhJM2swaVJRS2xVVQpaSkdUcnFCQm1kU3AzcnNRMWsvSmtqOVlLZEVRMHVmcTdNeDBzcEdqZ2NVd2djSXdEZ1lEVlIwUEFRSC9CQVFECkFnS2tNQk1HQTFVZEpRUU1NQW9HQ0NzR0FRVUZCd01CTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME8KQkJZRUZJWlUrUHlTYVB0eFdOV0RqckJ5SUZuVXdTL0JNR3NHQTFVZEVRUmtNR0tDQldGc2FXTmxnZ2xzYjJOaApiR2h2YzNTQ0JXRnNhV05sZ2c1d2IyeGhjaTF1TWkxaGJHbGpaWUlFZFc1cGVJSUtkVzVwZUhCaFkydGxkSUlIClluVm1ZMjl1Ym9jRWZ3QUFBWWNRQUFBQUFBQUFBQUFBQUFBQUFBQUFBWWNFckJJQUFqQUtCZ2dxaGtqT1BRUUQKQWdOSUFEQkZBaUVBbDhnOERONStpRTA5c1ZZS2RoblExUmZWeWhhaTdLMG9xK2puV3NyNHpVNENJR2t6Nko4eQprTk4rSTRHT040UGNIWGN1QjRjWEt1aDJxVWFvd2IvZVBxV3YKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
admin_mac_base64= "AgEDbG5kAvgBAwoQ4MUVu75H5pCIGbg7qzbRfBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaIQoIbWFjYXJvb24SCGdlbmVyYXRlEgRyZWFkEgV3cml0ZRoWCgdtZXNzYWdlEgRyZWFkEgV3cml0ZRoXCghvZmZjaGFpbhIEcmVhZBIFd3JpdGUaFgoHb25jaGFpbhIEcmVhZBIFd3JpdGUaFAoFcGVlcnMSBHJlYWQSBXdyaXRlGhgKBnNpZ25lchIIZ2VuZXJhdGUSBHJlYWQAAAYgzSSZTiO2yEt9aP+zP95czvfNNPgQXhyLNto2X1onfqQ="
admin_tls = NodeManager.convert_base64_to_file(file_name: "test_tls.cert", base64data: admin_tls_base64)
admin_mac = NodeManager.convert_base64_to_file(file_name: "test.macaroon", base64data: admin_mac_base64)
admin_node = NodeManager.new(admin_tls, admin_mac, '127.0.0.1:10001')
puts admin_node.get_info
Thank you for your help,
A simple solution was to give the File.write function the 'wb' rights
def self.convert_base64_to_file(directory: nil, file_name:, base64data:)
if directory
file_path = [directory, file_name].join('/')
else
file_path = file_name
end
file = File.open("file_name", 'w') {|f| f.write(Base64.decode64(base64data)) }
return file_path
end
I hope that'll help someone!
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
I have used Typhoeus to stream a zip file to memory, then am iterating through each file to extract the XML doc. To read the XML file I used Nokogiri, but am getting an error, Errno::ENOENT: No such file or directory # rb_sysopen - my_xml_doc.xml.
I looked up the error and saw that ruby is most likely running the script in the wrong directory. I am a little confused, do I need to save the XML doc to memory first before I can read it as well?
Here is my code to clarify further:
Controller
def index
url = "http://feed.omgili.com/5Rh5AMTrc4Pv/mainstream/posts/"
html_response = Typhoeus.get(url)
doc = Nokogiri::HTML(html_response.response_body)
path_array = []
doc.search("a").each do |value|
path_array << value.content if value.content.include?(".zip")
end
path_array.each do |zip_link|
download_file = File.open zip_link, "wb"
request = Typhoeus::Request.new("#{url}#{zip_link}")
binding.pry
request.on_headers do |response|
if response.code != 200
raise "Request failed"
end
end
request.on_body do |chunk|
download_file.write(chunk)
end
request.run
Zip::File.open(download_file) do |zipfile|
zipfile.each do |file|
binding.pry
doc = Nokogiri::XML(File.read(file.name))
end
end
end
end
file
=> #<Zip::Entry:0x007ff88998373
#comment="",
#comment_length=0,
#compressed_size=49626,
#compression_method=8,
#crc=20393847,
#dirty=false,
#external_file_attributes=0,
#extra={},
#extra_length=0,
#filepath=nil,
#follow_symlinks=false,
#fstype=0,
#ftype=:file,
#gp_flags=2056,
#header_signature=009890,
#internal_file_attributes=0,
#last_mod_date=18769,
#last_mod_time=32626,
#local_header_offset=0,
#local_header_size=nil,
#name="my_xml_doc.xml",
#name_length=36,
#restore_ownership=false,
#restore_permissions=false,
#restore_times=true,
#size=138793,
#time=2016-10-17 15:59:36 -0400,
#unix_gid=nil,
#unix_perms=nil,
#unix_uid=nil,
#version=20,
#version_needed_to_extract=20,
#zipfile="some_zip_file.zip">
This is the solution I came up with:
Gems:
gem 'typhoeus'
gem 'rubyzip'
gem 'redis', '~>3.2'
Controller:
def xml_to_redis_list(url)
html_response = Typhoeus.get(url)
doc = Nokogiri::HTML(html_response.response_body)
#redis = Redis.new
path_array = []
doc.search("a").each do |value|
path_array << value.content if value.content.include?(".zip")
end
path_array.each do |zip_link|
download_file = File.open zip_link, "wb"
request = Typhoeus::Request.new("#{url}#{zip_link}")
request.on_headers do |response|
if response.code != 200
raise "Request failed"
end
end
request.on_body do |chunk|
download_file.write(chunk)
end
request.run
while download_file.size == 0
sleep 1
end
zip_download = Zip::File.open(download_file.path)
Zip::File.open("#{Rails.root}/#{zip_download.name}") do |zip_file|
zip_file.each do |file|
xml_string = zip_file.read(file.name)
check_if_xml_duplicate(xml_string)
#redis.rpush("NEWS_XML", xml_string)
end
end
File.delete("#{Rails.root}/#{zip_link}")
end
end
def check_if_xml_duplicate(xml_string)
#redis.lrem("NEWS_XML", -1, xml_string)
end
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
This is my method for uploading files:
name = file.original_filename
directory = "images/"
path = File.join(directory, name)
File.open(path, "wb") { |f| f.write(file.read) }
I need to rename the uploaded file - I want to give it a unique name. But how can I obtain the file name and the extension?
One way on how to rename the file is from the filename remove the extension (.jpg - remove last 4 chars), rename the file and then merge the name+extension.
But this is a bit dirty way. Is there something cleaner and more elegant?
A 'little' late but I put this answer for those who are still searching and get here.
photo = params[:photo]
name = photo.original_filename
directory = "public/uploads/photos"
path = File.join(directory, name)
uniq_name = (0...10).map { (65 + rand(26)).chr }.join
time_footprint = Time.now.to_formatted_s(:number)
File.open(path, "wb") do |file|
file.write(photo.read)
#uniq_path = File.join(directory, uniq_name + time_footprint + File.extname(file))
File.rename(file, #uniq_path)
end
I take the random string generation from How to generate a random string in Ruby. And set #uniq_path to use it on a create function after.
What about doing this?
File.rename(file, folder_path + "/" + new_name + File.extname(file))
For example, calling this script on the same folder of the file:
new_name = "TESTING"
File.open("test.txt") do |file|
File.rename(file, new_name + File.extname(file))
end
Will rename the file to: TESTING.txt