I am looking for a way to create multiple csv files and download them as one zip archive within one request in my rails application.
To build the archive I use rubyzip gem - to download it just the rails built-in function send_data. The problem I have is that rubyzip's add-function requires a pathname to load files from. But there is no path as my csv files are created within the same request.
Some Code:
# controller action to download zip
def download_zip
zip = @company.download_all
send_data zip, filename: "abc.zip", type: 'application/zip'
end
# method to create zip
def download_all
Zip::File.open('def.zip', Zip::File::CREATE) do |zipfile|
self.users.each do |user|
#some magic to combine zipfile.add() and user.to_csv
end
end
end
# method to create csv
def to_csv
CSV.generate do |csv|
#build awesome csv
end
end
Is there a way to save my csv files temporarely at some directory, that I can pass a pathname to zipfile.add()?
Nice weekend everybody and happy coding!
You can do this by reading each CSV file into DataFrame and appending or concatenating the DataFrames to create a single DataFrame with data from all files. Here, I will use read_csv() to read CSV files and concat() function to concatenate DataFrams together to create one big DataFrame.
You could either write your CSV output into a temporary file and call zipfile.add() on that, but there is a cleaner solution:
zipfile.get_output_stream("#{user.name}.csv") { |f| f.puts(user.to_csv) }
See http://rdoc.info/github/rubyzip/rubyzip/master/Zip/File#get_output_stream-instance_method for more details on get_output_stream - you can also pass additional parameters to specify attributes for the file to be created.
get_output_stream
doesn't work for me. However, the updated method Zip::OutputStream.write_buffer
helps
https://gist.github.com/aquajach/7fde54aa9bc1ac03740feb154e53eb7d
The example adds password protection to the file as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With