Upload Files to Database in Rails 4 Without Paperclip
Bài đăng này đã không được cập nhật trong 8 năm
I. Giới thiệu
Như đã biết thì gem Paperclip
là một gem rất hữu dụng trong các app Rails nhưng nó không support cho việc save file vào trong database. Trong một số tình huống, truy cấp vòa filesystem hoặc dịch vụ bên ngoài như Amazon S3 thì không được khả thi. Hoặc đơn giản là muố đưa các files vào trong cơ sở dữ liệu.
II. Hướng dẫn cách làm
- Đầu tiên, tạo một
model
để lưu thông tin file.
- filename:string
- content_type:string
- fine_contents:binary
-
Note: để tạo nhanh 1 model như trên ta có thể sử dụng:
rails g scaffold document filename:string content_type:string file_contents:binary
-
Dưới đây là: code for model và file migration
# app/models/document.rb
class Document < ActiveRecord::Base
end
# db/migrate/20140602005921_create_documents.rb
class CreateDocuments < ActiveRecord::Migration
def change
create_table :documents do |t|
t.string :filename
t.string :content_type
t.binary :file_contents
t.timestamps
end
end
end
- Tiếp theo chúng ta sẽ thêm file input cho model's form
<!-- app/views/documents/_form.html.erb -->
<%= form_for(@document) do |f| %>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
- Tiếp đến, chúng ta cần đảm bảo rằng phải permit
params[:file]
, bởi thế chúng ta mới sử dụng đượcfile
trong model
# app/controllers/documents_controller.rb
def document_params
params.require(:document).permit(:file)
end
- Cuối cùng update cho model có thể đọc và lưu file lại. Ở trong Rails, thì file input được passed như là một UploadedFile, có thể coi nó như một normal file. Chúng ta sẽ viết một hàm
initialize
trong model:
# app/models/document.rb
def initialize(params = {})
file = params.delete(:file)
super
if file
self.filename = sanitize_filename(file.original_filename)
self.content_type = file.content_type
self.file_contents = file.read
end
end
private
def sanitize_filename(filename)
# Get only the filename, not the whole path (for IE)
# Thanks to this article I just found for the tip: http://mattberther.com/2007/10/19/uploading-files-to-a-database-using-rails
return File.basename(filename)
end
- Bây giờ chúng ta có một app mà ở đó users có thể upload files lên, nhưng vẫn chưa thể download được. Chúng ta có thể tao ra
show
action trongdocuments_controller
để download file. Để làm như vậy chỉ cận gửi các file đã lưu trong DB.
def show
send_data(@document.file_contents,
type: @document.content_type,
filename: @document.filename)
end
- Okey. Giờ chúng ta đã có 1 app Rails có thể upload và download file 1 cách rất đơn giản. Chúng ta có thể viết
validate
cho việc upload file, ví dụ như MB size, name ...
# app/models/document.rb
validate :file_size_under_one_mb
def initialize(params = {})
# File is now an instance variable so it can be
# accessed in the validation.
@file = params.delete(:file)
super
if @file
self.filename = sanitize_filename(@file.original_filename)
self.content_type = @file.content_type
self.file_contents = @file.read
end
end
NUM_BYTES_IN_MEGABYTE = 1048576
def file_size_under_one_mb
if (@file.size.to_f / NUM_BYTES_IN_MEGABYTE) > 1
errors.add(:file, 'File size cannot be over one megabyte.')
end
end
- Vừa rồi chúng ta vừa tạo ra một application Rails có thể upload và download file.
- Link APP DEMO
- Source GITHUB
III. Tài liệu tham khảo
All rights reserved