Tôi đã thực hiện việc này trên trang web nơi mọi người trả tiền để tải xuống một số tệp nhất định và các tệp được lưu trữ trong RAILS_ROOT/private
. Điều đầu tiên cần biết là bạn muốn máy chủ web xử lý việc gửi tệp, nếu không, ứng dụng của bạn sẽ được lưu trữ truyền tệp lớn và điều này sẽ nhanh chóng làm cho trang web của bạn bị tạm dừng nếu bạn có bất kỳ loại tải xuống nào. Vì vậy, nếu bạn cần phải kiểm tra ủy quyền trong một bộ điều khiển, sau đó bạn cũng cần một cách để vượt qua kiểm soát tải về trở lại máy chủ web. Cách tốt nhất để làm điều này (mà tôi biết) là tiêu đề X-Sendfile, được hỗ trợ bởi Nginx, Apache (với mô đun), và những thứ khác. Với X-Sendfile được cấu hình, khi máy chủ web của bạn nhận được tiêu đề từ ứng dụng của bạn, nó sẽ tiếp quản việc gửi tệp cho khách hàng.
Một khi bạn có X-Sendfile làm việc cho máy chủ web của bạn, một phương pháp điều khiển riêng như thế này rất hữu ích:
##
# Send a protected file using the web server (via the x-sendfile header).
# Takes the absolute file system path to the file and, optionally, a MIME type.
#
def send_file(filepath, options = {})
options[:content_type] ||= "application/force-download"
response.headers['Content-Type'] = options[:content_type]
response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filepath)}\""
response.headers['X-Sendfile'] = filepath
response.headers['Content-length'] = File.size(filepath)
render :nothing => true
end
Sau đó hành động điều khiển của bạn có thể trông giống như thế này:
##
# Private file download: check permission first.
#
def download
product = Product.find_by_filename!(params[:filename])
if current_user.has_bought?(product) or current_user.is_superuser?
if File.exist?(path = product.filepath)
send_file path, :content_type => "application/pdf"
else
not_found
end
else
not_authorized
end
end
Rõ ràng phương thức ủy quyền của bạn sẽ thay đổi và bạn sẽ cần thay đổi tiêu đề nếu bạn đang cung cấp tệp không phải PDF hoặc bạn muốn tệp được xem trong trình duyệt (loại bỏ loại nội dung application/force-download
).
Nguồn
2010-01-26 23:12:09
Tại sao điều này không sử dụng phương thức send_file được xây dựng? –
Bởi vì tôi không biết về nó! Bất kỳ ai sử dụng kỹ thuật này nên loại bỏ định nghĩa phương thức 'send_file' bị tê liệt của tôi và thay vào đó gọi đường dẫn' send_file' của Rails,: type => "application/pdf",: x_sendfile => true'. Cảm ơn vì lưu ý, Ryan. –
Tôi đã nhận xét thêm về 'X-Sendfile' tại: http://stackoverflow.com/a/26884350/895245 –