aboutsummaryrefslogblamecommitdiffstats
path: root/lib/active_storage/service/s3_service.rb
blob: ad55db0dc0cbb97ecf0d421eb2f918c30b16ec28 (plain) (tree)
1
2
3
4
5
6
7
8
9
                 
                                               
 
                                                                

                              


                                                           

     
                                    

                                                  
                                                                                   



                                           

     
                           
                   
                                            
                                                          
         
        
                                  


                                                                           
         



                 
                              
                                                   
       

     
                 
                                       







                                                     
       

     
                                                    
                                     

                                                          
                                                                                
       

     

                                                                             

                                                          
                                                                  


       
         

                                                          

       
require "aws-sdk"
require "active_support/core_ext/numeric/bytes"

class ActiveStorage::Service::S3Service < ActiveStorage::Service
  attr_reader :client, :bucket

  def initialize(bucket:, client: nil, **client_options)
    @bucket = bucket
    @client = client || Aws::S3::Client.new(client_options)
  end

  def upload(key, io, checksum: nil)
    instrument :upload, key, checksum: checksum do
      begin
        client.put_object bucket: bucket, key: key, body: io, content_md5: checksum
      rescue Aws::S3::Errors::BadDigest
        raise ActiveStorage::IntegrityError
      end
    end
  end

  def download(key, &block)
    if block_given?
      instrument :streaming_download, key do
        client.get_object bucket: bucket, key: key, &block
      end
    else
      instrument :download, key do
        "".b.tap do |data|
          client.get_object bucket: bucket, key: key, response_target: data
        end
      end
    end
  end

  def delete(key)
    instrument :delete, key do
      client.delete_object bucket: bucket, key: key
    end
  end

  def exist?(key)
    instrument :exist, key do |payload|
      payload[:exist] =
        begin
          client.head_object bucket: bucket, key: key
        rescue Aws::S3::Errors::NoSuckKey
          false
        else
          true
        end
    end
  end

  def url(key, expires_in:, disposition:, filename:)
    instrument :url, key do |payload|
      payload[:url] = presigner.presigned_url :get_object,
        bucket: bucket, key: key, expires_in: expires_in,
        response_content_disposition: "#{disposition}; filename=\"#{filename}\""
    end
  end

  def url_for_direct_upload(key, expires_in:, content_type:, content_length:)
    instrument :url, key do |payload|
      payload[:url] = presigner.presigned_url :put_object,
        bucket: bucket, key: key, expires_in: expires_in,
        content_type: content_type, content_length: content_length
    end
  end

  private
    def presigner
      @presigner ||= Aws::S3::Presigner.new client: client
    end
end