Save image from ZIP file using rubyzip, paperclip, and rails 4 - ruby

Let me start by saying I'm open to a better way to do this, but here's what I have so far.
Lets say I have a zip file with 100 images in it. I want to loop through the zip file and 'attach' each image to a record. I have Paperclip installed to attach the image to the record in ActiveRecord. I'm using the following code so far:
Zip::File.open(params['images'].path) do |zipfile|
zipfile.each do |file|
# THIS IS WHAT I'M MISSING
end
end
This is what I'd like to end up with:
Zip::File.open(params['images'].path) do |zipfile|
zipfile.each do |file|
MyModel.create(parent_id: 1, image: "...")
end
end
How could I do that?

you should create tempfile from zip, than create paperclip attachment with this tempfile
Zip::File.open(params['images'].path) do |zipfile|
zipfile.each do |file|
tempfile = Tempfile.new(File.basename(file.name))
tempfile.binmode
tempfile.write file.get_input_stream.read
# to save original file name to model, use image_file_name
MyModel.create(parent_id: 1, image: tempfile, image_file_name: file.name)
tempfile.close
end
end

Related

rubyzip: open zip, modify it temporary, send to client

i want to temporary modify a zip file and send the changed file to the client.
right now i create a file stream and send it:
require 'zip'
zip_stream = Zip::OutputStream.write_buffer do |zip|
zip.put_next_entry 'new_folder/file'
zip.print "some text"
end
zip_stream.rewind
send_data zip_stream.read, type: 'application/zip', disposition: 'attachment', filename: 'thing.zip'
i dont get how i can open a existing zip in the filesystem and put additional file in it and send it without saving it do the disk.
can you give me a hint?
in the end i did it like this:
require 'zip'
zip_stream = Zip::OutputStream.write_buffer do |new_zip|
existing_zip = Zip::File.open('existing.zip')
existing_zip.entries.each do |e|
new_zip.put_next_entry(e.name)
new_zip.write e.get_input_stream.read
end
new_zip.put_next_entry 'new_file'
new_zip.print "text"
end
Check this https://github.com/rubyzip/rubyzip
require 'rubygems'
require 'zip'
folder = "Users/me/Desktop/stuff_to_zip"
input_filenames = ['image.jpg', 'description.txt', 'stats.csv']
zipfile_name = "/Users/me/Desktop/archive.zip"
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
input_filenames.each do |filename|
# Two arguments:
# - The name of the file as it will appear in the archive
# - The original file, including the path to find it
zipfile.add(filename, File.join(folder, filename))
end
zipfile.get_output_stream("myFile") { |f| f.write "myFile contains just this" }
end

Create zip archive without save archiving file to disk in Ruby

I tried to create zip archive without save archiving file to disk. So First I write method with save to disk:
begin
file = Zip::File.open("#{file_name}.zip", Zip::File::CREATE)
save_file file_name
file.add(file_name, file_name)
rescue IOError => e
puts "Error: #{e}"
ensure
file.close unless file.nil?
File.delete file_name
end
This work fine but before create save archiving file.
Second I tried to write this code, first create StringIO zip archive with file witch I need, second I cant save them to disk in bin mode:
string_io = Zip::OutputStream.write_buffer do |zos|
zos.put_next_entry(file_name)
zos.write dictionary.join(', ')
end
# Something wrong below
File.open("#{file_name}.zip", 'wb') do |file|
file.write string_io
file.close
end
What a do wrong? and how to do it right way?
Found!
string_io = Zip::OutputStream.write_buffer do |zos|
zos.put_next_entry(file_name)
zos.write dictionary.join(', ')
end
# Rewind
string_io.rewind
# Write simply to file in bin mode
IO.write("#{file_name}.zip", string_io.sysread)

Making subdirectories while copying files

I have simple script that goes through txt file and copies files according to line in txt file
Here is it
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop #need to remove \n symbol from like
system("cp #{line} new/#{line}")
end
end
In my txt files - there are file path in each like like:
app/helpers/api/v1/application_helper.rb
However when i run script it fails if there is no such directory inside my new folder. So either i have to create them manually to reflect folder structure as in my txt file, or create with script.
Is there any way how can i do this in my script?
There are many ways to solve this. Here's one method:
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop
system("mkdir -p new/#{File.dirname(line)}")
system("cp #{line} new/#{line}")
end
end
I see you're requiring fileutils but not using any of its methods. You can use it like this
require 'fileutils'
File.open("files.txt", "r") do |f|
f.each_line do |line|
line = line.chop #need to remove \n symbol from like
FileUtils.mkdir_p(File.dirname(line))
FileUtils.cp(line, "new/#{line}")
end
end

Zipping an existing file with Rubyzip

I would like to use rubyzip to archive "zip" an existing file:
c:\textfile.txt
to
textfile.zip
I know how to add a stream to a text file:
require 'zip/zip'
Zip::ZipFile.open("mp.zip", Zip::ZipFile::CREATE) {
|zipfile|
zipfile.get_output_stream("text.txt") { |f| f.puts "Creating text file" }
}
but not how to add an existing file to a zip. Thanks for your help
This reads in the source file and writes it 1mb at a time to the zipfile.
I've been using something very similar in production for some time now.
require 'zip/zip'
Zip::ZipFile.open("mp.zip", Zip::ZipFile::CREATE) do |zipfile|
zipfile.get_output_stream("text.txt") do |out_file|
File.open("text.txt") do |in_file|
while blk = in_file.read(1024**2)
out_file << blk
end
end
end
end
Hope this answers your question.

Saving output of a query onto a text file in Ruby

I'm trying to query a table, fetch all records, and save the result as a CSV file.
This is what I've done so far:
require 'OCI8'
conn = OCI8.new('scott','tiger','020')
file = File.open('output.csv','w') do |f|
conn.exec('select * from emp') do |e|
f.write log.join(',')
end
end
.. And while it does generate a CSV file, the problem is that all records get saved onto a single line. How can I put the data such that each record goes onto a new line ?
Well, you can use f.puts instead of f.write there, but I'd recommend you take a look at CSV module:
http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html
outfile = File.open('csvout', 'wb')
CSV::Writer.generate(outfile) do |csv|
csv << ['c1', nil, '', '"', "\r\n", 'c2']
...
end
outfile.close
PS: Actually, there is another CSV library called FasterCSV, which became CSV in standard library in Ruby 1.9. But in general, any should be better than writing it yourself.

Resources