From 390097531bd17369f05a23eba58c37b850ac95dd Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Sun, 15 Jul 2018 19:58:14 -0400 Subject: Support HTTP Range downloads from disk Closes #32193. --- .../controllers/active_storage/disk_controller.rb | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'activestorage/app/controllers') diff --git a/activestorage/app/controllers/active_storage/disk_controller.rb b/activestorage/app/controllers/active_storage/disk_controller.rb index 63918eb6f4..436cd0ccd8 100644 --- a/activestorage/app/controllers/active_storage/disk_controller.rb +++ b/activestorage/app/controllers/active_storage/disk_controller.rb @@ -5,23 +5,14 @@ # Always go through the BlobsController, or your own authenticated controller, rather than directly # to the service url. class ActiveStorage::DiskController < ActiveStorage::BaseController - include ActionController::Live - skip_forgery_protection def show if key = decode_verified_key - response.headers["Content-Type"] = params[:content_type] || DEFAULT_SEND_FILE_TYPE - response.headers["Content-Disposition"] = params[:disposition] || DEFAULT_SEND_FILE_DISPOSITION - - disk_service.download key do |chunk| - response.stream.write chunk - end + serve_file disk_service.path_for(key), content_type: params[:content_type], disposition: params[:disposition] else head :not_found end - ensure - response.stream.close end def update @@ -32,13 +23,9 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController else head :unprocessable_entity end - else - head :not_found end rescue ActiveStorage::IntegrityError head :unprocessable_entity - ensure - response.stream.close end private @@ -51,6 +38,20 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key) end + def serve_file(path, content_type:, disposition:) + Rack::File.new(nil).serving(request, path).tap do |(status, headers, body)| + self.status = status + self.response_body = body + + headers.each do |name, value| + response.headers[name] = value + end + + response.headers["Content-Type"] = content_type || DEFAULT_SEND_FILE_TYPE + response.headers["Content-Disposition"] = disposition || DEFAULT_SEND_FILE_DISPOSITION + end + end + def decode_verified_token ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token) -- cgit v1.2.3