Masroor Hussain
Posted on April 4, 2021
Recently I worked on a project where I had to upload a zip archive of images and then attach those images to Active Record
model objects on the Rails server.
- Note:
This example uses
Active Storage
to attach images toActive Record
objects.
Here is how I got it all working
Install Gem
Include this gem
gem 'rubyzip'
then do
bundle install
Unzipping and file attachment
We suppose an Active Record
model named Product
, which has an Active Storage
attribute called product_image
class OrderItem < ApplicationRecord
has_one_attached :product_image
end
The controller which renders a zip upload form in the action zip_upload_form
(view template code is not provided here) and the form gets posted to the zip_file
action, which then processes the zip file by calling the process_zip_file
method. It's better to put such code in a service but for the sake of this tutorial let's just put in the controller.
require 'zip'
class UnzipController < ApplicationController
# GET
def zip_upload_form
# this action renders form for zip file upload
end
# POST
def zip_file
# the form is posted to this action
# this action processes the uploaded zip file
# params[:zip] is the uploaded zip file
if params[:zip]
process_zip_file(params[:zip])
else
redirect_to zip_upload_form_path
end
end
private
def process_zip_file(tmpfile_zip)
Zip::File.open(tmpfile_zip.path) do |zipfile|
# iterating through all the entries found in the zip file
zipfile.each do |entry|
if entry.file?
puts "#{entry.name} is a file!"
attach_file_to_model_obj(entry)
elsif entry.directory?
puts "#{entry.name} is a directory!"
elsif entry.symlink?
puts "#{entry.name} is a symlink!"
end
end
end
end
def attach_file_to_model_obj(entry)
# first we create a temp file from the file found in the zip archive
# then attach the temp file to model obj
Tempfile.open(["my-filename", ".#{put_extension_here}"]) do |tmp|
# this line creates the temp file
entry.extract(tmp.path) { true }
# attaching the temp image file to active record object
Product.first
.product_image
.attach(io: File.open(tmp.path), filename: "my-filename.#{put_extension_here}")
end
end
end
Cover Image by JOHN TOWNER on Unsplash
Posted on April 4, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.