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

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.

Related

When I download Excel files, strange files are stored

I want to download uploaded files such as .zip, .xlsm, xlsx, pdf... ..., etc., that have been uploaded, I want to eventually compress them into a zip file for download.
However, if the uploaded files are not zipped, they will be downloaded with strange files stored in them.
In this case, .xlsm
Source Code
class DownloadZipsController < ::ApplicationController
def index
file_name = "#{Time.current.strftime("%Y%m%d_%H%M%S")}.zip"
zip_file = Tempfile.new(file_name)
Zip.unicode_names = true
Zip::OutputStream.open(zip_file.path) do |zip|
params[:product_ids].each do |product_id|
product = Product.find(product_id)
zip.put_next_entry("output.zip")
zip.print Net::HTTP.get URI.parse(product.submit_zip_file.url)
end
end
send_file zip_file.path,
type: "application/zip",
disposition: "attachment",
filename: file_name
zip_file.close
rescue => e
logger.debug e.backtrace
redirect_to request.referer, alert: e.message
end
end
Uploaded files are stored in AWS S3.
Is there any solution to this problem?
Office Documents such as .xlsm, .xlsx, .docx, and others are in fact zip files containing the document as a xml file plus additional resources.
The file tree you have shown in your screenshot shows the content of one such document if you interpret it as a zip file and unpack.
It appears that somewhere in your code, you have detected the document file as a zip file and interpreted it as such which resulted in its contents to be unpacked.
This is not apparent from the code you have posted though, so I would assume that you have some additional handling of zip files somewhere else (such as a function to download existing files which may then be send with a wrong content type to the browser, i.e as an application/zip rather than application/vnd.ms-excel.sheet.macroEnabled.12).

How to send the zip file in Rails via Grape API

I have a set of files that are present in s3 and I have to zip them all and send the zipped file to the front end(ReactJS).
I am successfully able to create a folder in the tmp of the project and also zip them. Unfortunately, I get the error when I try to expand saying Unable to expand
Here is the code -
data = Zip::File.open(zip_file_name, ::Zip::File::CREATE) do |zipfile|
files.each do |file|
zipfile.add(file, file_path)
end
end
content_type "application/octet-stream"
header['Content-Disposition'] = "attachment; filename=abcd.zip"
env['api.format'] = :binary
File.open(zip_file_name, 'rb').read
Is there a way to solve the problem? Thanks

Testing File Creation in 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!

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/ .

Ruby Net::FTP, extract filename from ftp.list()

I'm using the following code to try and get all files from ftp using Ruby.
files = ftp.list()
files.each do |file|
ftp.gettextfile(file)
end
The problem is ftp.list returns a whole line of information, not just the filename e.g.
-rw-r--r-- 1 ftp ftp 0 May 31 11:18 brett.txt
How do I extract the filname from this string?
Many thanks
You can use the nlst public method like this
files = ftp.nlst("*.zip")|ftp.nlst("*.txt")|ftp.nlst("*.xml")
#optionally exclude falsely matched files
exclude = /\.old|temp/
#exclude files with 'old' or 'temp' in the name
files = files.reject{ |e| exclude.match e } #remove files matching the exclude regex
files.each do |file|
#do something with each file here
end
If you want to process the output of ftp.list you may find net-ftp-list useful.
However, list appears to be useful, as you can pass in a matching pattern, which it doesn't appear that nlst supports. I just did a quick-and-dirty hack to make list output work:
ftp.list("*.zip") do |zipfile|
zipfile = zipfile.split(/\s+/).last
# ... do something with the file
end

Resources