Created
November 18, 2015 14:21
-
-
Save danhorst/e6dc6110883c965bb60b to your computer and use it in GitHub Desktop.
Hydra::Controller::DownloadBehavior from hydra-core 6.4.2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Hydra | |
module Controller | |
module DownloadBehavior | |
extend ActiveSupport::Concern | |
included do | |
before_filter :load_asset | |
before_filter :load_datastream | |
end | |
# Responds to http requests to show the datastream | |
def show | |
if can_download? | |
if datastream.new? | |
render_404 | |
else | |
# we can now examine asset and determine if we should send_content, or some other action. | |
send_content (asset) | |
end | |
else | |
logger.info "Can not read #{params[asset_param_key]}" | |
raise Hydra::AccessDenied.new("You do not have sufficient access privileges to read this document, which has been marked private.", :read, params[asset_param_key]) | |
end | |
end | |
protected | |
def render_404 | |
respond_to do |format| | |
format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found } | |
format.any { head :not_found } | |
end | |
end | |
# Override this method if asset PID is not passed in params[:id], | |
# for example, in a nested resource. | |
def asset_param_key | |
:id | |
end | |
def load_asset | |
@asset = ActiveFedora::Base.load_instance_from_solr(params[asset_param_key]) | |
end | |
def load_datastream | |
@ds = datastream_to_show | |
end | |
def asset | |
@asset | |
end | |
def datastream | |
@ds | |
end | |
# Override this method to enforce access controls. By default it allows | |
# any datastream on an object the current user has read access to. | |
# @return [Boolean] can the curent user view this object/datastream | |
def can_download? | |
can? :read, datastream.pid | |
end | |
# Override this method to change which datastream is shown. | |
# Loads the datastream specified by the HTTP parameter `:datastream_id`. | |
# If this object does not have a datastream by that name, return the default datastream | |
# as returned by {#default_content_ds} | |
# @return [ActiveFedora::Datastream] the datastream | |
def datastream_to_show | |
ds = asset.datastreams[params[:datastream_id]] if params.has_key?(:datastream_id) | |
ds = default_content_ds if ds.nil? | |
raise "Unable to find a datastream for #{asset}" if ds.nil? | |
ds | |
end | |
# Handle the HTTP show request | |
def send_content(asset) | |
response.headers['Accept-Ranges'] = 'bytes' | |
if request.head? | |
content_head | |
elsif request.headers['HTTP_RANGE'] | |
send_range | |
else | |
send_file_headers! content_options | |
self.response_body = datastream.stream | |
end | |
end | |
# Create some headers for the datastream | |
def content_options | |
{disposition: 'inline', type: datastream.mimeType, filename: datastream_name} | |
end | |
# Override this if you'd like a different filename | |
# @return [String] the filename | |
def datastream_name | |
params[:filename] || asset.label | |
end | |
# render an HTTP HEAD response | |
def content_head | |
response.headers['Content-Length'] = datastream.dsSize | |
response.headers['Content-Type'] = datastream.mimeType | |
head :ok | |
end | |
# render an HTTP Range response | |
def send_range | |
_, range = request.headers['HTTP_RANGE'].split('bytes=') | |
from, to = range.split('-').map(&:to_i) | |
to = datastream.dsSize - 1 unless to | |
length = to - from + 1 | |
response.headers['Content-Range'] = "bytes #{from}-#{to}/#{datastream.dsSize}" | |
response.headers['Content-Length'] = "#{length}" | |
self.status = 206 | |
send_file_headers! content_options | |
self.response_body = datastream.stream(from, length) | |
end | |
private | |
def default_content_ds | |
ActiveFedora::ContentModel.known_models_for(asset).each do |model_class| | |
return asset.datastreams[model_class.default_content_ds] if model_class.respond_to?(:default_content_ds) | |
end | |
if asset.datastreams.keys.include?(DownloadsController.default_content_dsid) | |
return asset.datastreams[DownloadsController.default_content_dsid] | |
end | |
end | |
module ClassMethods | |
def default_content_dsid | |
"content" | |
end | |
end | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment