Testing File Creation in Rails - ruby-on-rails

My App saves Files to the Filesystem via an base64 encoded API. Here is my (simplified) controller:
def create
file = "name.pdf"
folder = "downloads"
FileUtils::mkdir_p folder
f = File.open File.join(folder, file), "wb"
if f.write Base64.decode64(params[:file])
f.close
end
Now I want to test for an actual file creation. How do I check whether there is a file or not?
Thanks for your input!

Related

Rails: Rename a Binary File uploaded to API

I've seen a lot of threads that open up a file from a directory and rename it. But in my case, the user is uploading a file to a POST endpoint. I'd like to rename that file before uploading to my blob storage.
Here's what I have so far:
def picture
#file = params[:file]
#new_file_name = generate__filename()
#this line didn't work
File.rename(#file, #new_file_name + File.extname(#file))
# begin upload here
end
I'm testing this by selecting the form-data value as file in Postman. How do I rename this file?

Rails FTP OPEN CSV

I have the following code to connect my rails app to my FTP. This works great. However, I want to use open-uri to open the csv file so I can parse it. Any ideas how to do this? I think it's an easy thing to do but I'm missing something.
require 'net/ftp'
ftp = Net::FTP.new
ftp.connect("xxx.xxx.xx.xxx",21)
ftp.login("xxxxx","xxxx")
ftp.chdir("/")
ftp.passive = true
puts ftp.list("TEST.csv")
You'll need to use #gettextfile.
A) Get the file to a local temporary file and read its content
# Creating a tmp file can be done differently as well.
# It may also be omitted, in which case `gettextfile`
# will create a file in the current directory.
Dir::Tmpname.create(['TEST', ['.csv']) do |file_name|
ftp.gettextfile('TEST.csv', file_name)
content = File.read(file_name)
end
B) Pass a block to gettextfile and get the content one line at a time
content = ''
ftp.gettextfile('TEST.csv') do |line|
content << line
end

Concatenate bytes - Writing file to FTP folder as chunks

I'm writing an Rails app which could upload files to storage. Big files are splitted into chunks from client (with JS) and upload parts to server.
As in development, I could simply open existed file and write following bytes into that.
(I'm using CarrierWave gem)
File.open(#up_file.link.path, "ab") do |f|
f.write(up_file_params[:link].read)
end
# This code worked when I upload to '/public' folder in development
However, now I want to use a FTP server to storage files. But I can't Concatenate new bytes with existed bytes.
def get_ftp_connection # create a new FTP connection
ftp = Net::FTP.new
ftp.connect(ENV['ftp_host'], ENV['ftp_port'])
begin
ftp.passive = ENV['ftp_passive']
ftp.login(ENV['ftp_user'], ENV['ftp_passwd'])
yield ftp
ensure
ftp.quit
end
end
.....
def create
.....
get_ftp_connection #up_file do |ftp|
full_path = ::File.dirname "#{ENV['ftp_folder']}/#{#up_file.link.path}"
base_name = File.basename(#up_file.link.to_s)
ftp.chdir(full_path)
ftp.putbinaryfile(up_file_params[:link].read, base_name)
end
end
I got ArgumentError (string contains null byte): at putbinaryfile... , any help :(
As mentioned in the comments you could completely download the file first and then upload to the ftp server. If that's not an option for whatever reason, you could append to the remote file as it's being uploaded:
ftp.storbinary("APPE #{base_name}", up_file_params[:link], Net::FTP::DEFAULT_BLOCKSIZE)

Using Tempfile to create a zip file in rails

I want to create a temporary .zip in rails. For creating zip file I am using rubyzip gem.
Currently I am doing this:
zfname = Tempfile.new(['somename','.zip'], Rails.root.to_s + '/tmp/')
Zip::ZipFile.open(zfname.path, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
This generates following error:
Zip::ZipError: Zip end of central directory signature not found
Is it possible to use Tempfile for zip? If yes, what is wrong here?
In my rails app when I needed to send zip files to user, I just stored them in a buffer and used 'send data' method in controller.
I was trying to use 'Tempfile' initially but it had an added task of removing zip files after sending it to user which is a pain.
Is this something you are looking for?
Zip::OutputStream.write_buffer do |stream|
file_paths.each_with_index do |file_path, index|
# rename the pdf
stream.put_next_entry("#{name}-#{index + 1}.pdf")
# add pdf to zip
stream.write IO.read(file_path)
end
end
So it doesn't actually look like you need or want a Tempfile. You really want a random path in the Rails.root/tmp directory. Try something like this:
zfpath = Rails.root.join('tmp', "somename-#{SecureRandom.hex(8)}.zip"
Zip::ZipFile.open(zfpath, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
Update:
While it's far more complex, you can find a discussion of how to do this with a Tempfile here - http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/ .

rails rubyzip make a copy of multiple zip files inside a new zipfile

So basically I am creating a bunch of zip files which contains a pwe and pws files inside it.
The following code generates a bunch of zip files which is named as orgname_org_member_orguser1.zip
which contains 2 files(a pws and pwe)
#successful_orgs.each do |org|
file = "#{RAILS_ROOT}/my-data/#{org[:location]}_#{org[:member]}_#{org[:username]}.zip"
generate_file(ups_file, org)
end
def generate_file(file, org)
zipfile = Zip::ZipFile.open(file, Zip::ZipFile::CREATE)
pwe_text, pws_text = MyGenerator.password
pwe_file = "#{RAILS_ROOT}/tmp/#{org[:location]}_#{org[:member]}.pwe"
pws_file = "#{RAILS_ROOT}/tmp/#{org[:location]}_#{org[:member]}.pws"
File.open(pwe_file, 'w') { |file| file.write(pwe_text) }
File.open(pws_file, 'w') { |file| file.write(pws_text) }
zipfile.add("#{org[:location]}_#{org[:member]}.pwe", pwe_file)
zipfile.add("#{org[:location]}_#{org[:member]}.pws", pws_file)
zipfile.close
File.delete(pwe_file)
File.delete(pws_file)
end
I want to let the code do what is doing(create the zip files and store it the specified path)
But in addition to the above, I also want to create another zip file called all.zip which would contain all the zip files created above.
Meaning, all.zip => file1.zip, file2.zip etc
I am not sure how to incoporate that logic in my code above. Any help would be appreciated.
EDIT: I do not want to search and add all the files in the directory. I want to add only the zip files created during the above code.
You can collect all the zip file paths in an array and then add them to a new zip file iteratively:
zip_files = []
#successful_orgs.each do |org|
file = "#{RAILS_ROOT}/my-data/#{org[:location]}_#{org[:member]}_#{org[:username]}.zip"
zip_files << file
generate_file(file, org)
end
all_zipped = Zip::ZipFile.open("#{RAILS_ROOT}/tmp/all.zip", Zip::ZipFile::CREATE)
zip_files.each do |f|
all_zipped.add(zip_file)
end
Note that you're not going to gain any additional compression by doing this.

Resources