Newer
Older
class V1::LearningObjects::ChunksController < ApplicationController
# GET /learning_objects/:learning_object_id/chunk
def show
# chunk exist?
render status: File.exist?(chunk_file_path) ? 200 : 204
end
# POST /learning_objects/:learning_object_id/chunk
def create
if last_chunk?
combine_file!
attachment = post_file!
render json: attachment, status: :ok
end
rescue
render status: :internal_server_error
def authorize!
@learning_object = LearningObject.find chunks_params[:id]
authorize(@learning_object, :update?)
# Never trust parameters from the scary internet, only allow the white list through.
def chunks_params
params.permit(:id, :file, :_chunkNumber, :_totalChunks, :_chunkFilename, :_chunkIdentifier, :_chunkSize, :_currentChunkSize, :_totalSize)
def post_file!
publisher = LearningObjectPublisher.new(DspaceService.create_client)
publisher.upload @learning_object, final_file_path
##
# Move the temporary Sinatra upload to the chunk file location
def save_file!
return nil unless chunks_params[:file].try(:tempfile).is_a? Tempfile
# Ensure required paths exist
FileUtils.mkpath(chunk_file_directory)
# Move the temporary file upload to the temporary chunk file path
FileUtils.mv(chunks_params[:file].tempfile, chunk_file_path, force: true)
##
# Build final file
def combine_file!
# Ensure required paths exist
FileUtils.mkpath(final_file_directory)
# Open final file in append mode
File.open(final_file_path, 'a') do |f|
file_chunks.each do |file_chunk_path|
# Write each chunk to the permanent file
f.write File.read(file_chunk_path)
end
end
# Cleanup chunk file directory and all chunk files
FileUtils.rm_rf(chunk_file_directory)
end
def valid_mime_type?
mime_types = @learning_object.object_type.mime_types.map(&:extension)
return true if mime_types.empty?
mime_types.include? chunks_params[:_chunkFilename].split('.').last
end
##
# Determine if this is the last chunk based in parts count.
def last_chunk?
Dir["#{chunk_file_directory}/#{chunks_params[:_chunkFilename]}.part*"].count == chunks_params[:_totalChunks].to_i
# ./tmp/file-chunks/abc-123/upload.txt.part1
def chunk_file_path
File.join(chunk_file_directory, "#{chunks_params[:_chunkFilename]}.part#{chunks_params[:_chunkNumber]}")
def chunk_file_directory
File.join('tmp', 'file-chunks', chunks_params[:_chunkIdentifier])
# /tmp/file-chunks/upload.txt
def final_file_path
File.join(final_file_directory, chunks_params[:_chunkFilename])
def final_file_directory
File.join('tmp', 'files', chunks_params[:_chunkIdentifier])
end
##
# Get all file chunks sorted by cardinality of their part number
def file_chunks
Dir["#{chunk_file_directory}/*.part*"].sort_by { |f| f.split('.part')[1].to_i }