Rails zip files before download

Rails zip files before download

rails zip files before download

of images from their URLs, create a zip file and create a link to download it. http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/ If the user has already made a move before the turn ends, it'd kill the job and. The core of the CV Partner web application was written in Ruby on Rails 8 years ago and is as an export format, the file would be downloaded with the.zip file extension. Before our last major update migration we knew that this worked. send the file directly because it will #get deleted before rails actually starts sending it send_data(zip_data:type => 'application/zip':filename.

In our day-to-day activities we are often interacting with archives. When you want to send your friend a bunch of documents, you’d probably archive them first. When you download a book from the web, it will probably be archived alongside with accompanying materials. So, how can we interact with archives in Ruby?

Today we will discuss a popular gem called rubyzip that is used to manage zip archives. With its help, you can easily read and create archives or generate them on the fly. In this article I will show you how to create database records from the zip file sent by the user and how to send an archive containing all records from a table.

Source code is available at GitHub.

Before getting started, I want to remind you that various compressed formats have different compression ratios. As such, even if you archive a file, its size might remain more or less the same:

  • Text files compress very nicely. Depending on their contents, the ratio is about 3:1.
  • Some images can benefit from compression, but when using a format like .jpg that already has native compression, it won’t change much.
  • Binary files may be compressed up to 2 times of their original size.
  • Audio and video are generally poor candidates for compression.

Getting Started

Create a new Rails app:

I am using Rails 5 beta 3 and Ruby 2.2.3 for this demo, but rubyzip works with Ruby 1.9.2 or higher.

In our scenario today, the demo app keeps track of animals. Each animal has the following attributes:

  • ()
  • () – of course, you can use decimal instead
  • ()

We want to list all the animals, add abilities to them, and download data about them in some format.

Create and apply the corresponding migration:

Now let’s prepare the default page for our app:

animals_controller.rb

views/animals/index.html.erb

config/routes.rb

Nice! Proceed to the next section and let’s take care of creation first.

Creating Animals from the Archive

Introduce the action:

animals_controller.rb

*views/animals/index.html.erb

Of course, we could craft a basic Rails form to add animals one by one, but instead let’s allow users to upload archives with JSON files. Each file will then contain attributes for a specific animal. The file structure looks like this:

  • animals.zip
    • animal-1.json
    • animal-2.json

Each JSON file will have the following structure:

Of course, you may use another format, like XML, for example.

Our job is to receive an archive, open it, read each file, and create records based on the input. Start with the form:

views/animals/new.html.erb

This is a basic form allowing the user to select a file (don’t forget the option).

Now the controller’s action:

animals_controller.rb

The only parameter that we are interested in is the . As long as it contains a file, it responds to the method that returns path to the uploaded file.

To read an archive we will use the method that accepts a block. Inside this block you can fetch each archived file and either extract it somewhere by using or read it into memory with the help of . We don’t really need to extract our archive anywhere, so let’s instead store the contents in the memory.

animals_controller.rb

Pretty simple, isn’t it? reads the file’s contents and parses it. We are only interested in .json files though, so let’s limit the scope using the method:

animals_controller.rb

You can also extract part of the code to the model and introduce a basic error handling:

animals_controller.rb

animal.rb

I also want to whitelist attributes that the user can assign preventing him from overriding or fields:

animal.rb

You may use a blacklist approach instead by replacing with except, but whitelisting is more secure.

Great! Now go ahead, create a zip archive and try to upload it!

Generating and Downloading an Archive

Let’s perform the opposite operation, allowing the user to download an archive containing JSON files representing animals.

Add a new link to the root page:

views/animals/index.html.erb

We’ll use the same action and equip it with the method:

animals_controller.rb

To send an archive to the user, you may either create it somewhere on the disk or generate it on the fly. Creating the archive on disk involves the following steps:

  • Create an array of files that has to be placed inside the archive:
  • Add your files to the archive:

The method accepts two arguments: the file name as it should appear in the archive and the original file’s path and name.

  • Send the archive:

    This, however, means that all these files and the archive itself will persist on disk. Of course, you may remove them manually and even try to create a temporary zip file as described here but that involves too much unnecessary complexity.

What I’d like to do instead is to generate our archive on the fly and use send_data method to display the response as an attachment. This is a bit more tricky, but there is nothing we can’t manage.

In order to accomplish this task, we’ll require a method called that accepts a block:

animals_controller.rb

To add a new file to the archive, use while providing a file name. You can even specify a directory to nest your file by saying . To write something to the file, use :

animals_controller.rb

We don’t want fields like or to be present in the file, so by saying we limit them to , and .

Now rewind the stream:

And send it:

Here is the resulting code:

animals_controller.rb

Go ahead and try the “Download archive” link!

You can even protect the archive with a password. This feature of rubyzip is experimental and may change in the future, but it seems to be working currently:

animals_controller.rb

Customizing Rubyzip

Rubyzip does provide a bunch of configuration options that can be either provided in the block:

or one-by-one:

Here are the available options:

  • – Should the existing files be overwritten during extraction? Default is .
  • – Should the existing files be overwritten while creating an archive? Default is .
  • – Set this if you want to store non-unicode file names on Windows Vista and earlier.Default is .
  • – Should a warning be displayed if an archive has incorrect date format? Default is .
  • – Default compression level to use. Initially set to , other possible values are and .
  • – Should Zip64 support be disabled for writing? Default is .

Conclusion

In this article we had a look the rubyzip library. We wrote an app that reads users’ archives, creates records based on them, and generates archives on the fly as a response. Hopefully, the provided code snippets will come in handy in one of your projects.

As always, thanks for staying with me and see you soon!

Источник: https://www.sitepoint.com/accept-and-send-zip-archives-with-rails-and-rubyzip/

Rails zip files before download

1 thoughts to “Rails zip files before download”

Leave a Reply

Your email address will not be published. Required fields are marked *