require 'digest' class Api::V2::FileStorageController < ApplicationController skip_before_filter :authorize, :only => [:save, :serve] before_filter :authorize_admin_api_token, :only => [:save] def save if params[:contents].is_a?(ActionDispatch::Http::UploadedFile) params[:contents].close(false) # close and don't delete so we can import it tmp_file = params[:contents] else raise "No upload to process." end uploaded_file = nil sha = Digest::SHA512.file tmp_file.path sha.hexdigest UploadedFile.connection.transaction do uploaded_file = UploadedFile.find_or_initialize_by(filename: params[:filename]) if uploaded_file && uploaded_file.file_oid # Remove old file UploadedFile.connection.execute "SELECT LO_UNLINK('#{uploaded_file.file_oid}')" end res = UploadedFile.connection.execute "SELECT LO_IMPORT('#{tmp_file.path}') AS file_oid" uploaded_file.file_oid = res[0]["file_oid"].to_i uploaded_file.checksum = sha.hexdigest uploaded_file.headers = params[:headers] uploaded_file.permissions = params[:permissions] || 'protected' uploaded_file.save! end File.unlink tmp_file.path render :json => uploaded_file.to_json, status: :created end def serve file = UploadedFile.find_by(filename: params[:filename]) if file.nil? render :text => "File not found.", content_type: "text/plain", status: 404 return end if !file.public? authorize() return unless signed_in? end # Make sure if file changes that it will bust the cache tmp_path = "#{Rails.root}/tmp/uploaded_file_#{file.file_oid}_#{file.updated_at.to_i}" if !File.exist?(tmp_path) UploadedFile.connection.execute "SELECT LO_EXPORT(#{file.file_oid}, '#{tmp_path}')" end send_file(tmp_path, type: file.mime_type, disposition: nil) file.headers.each do |k, v| response.headers[k] = v end unless file.headers.nil? end end