Module: Paperclip::Storage::Backblaze

Defined in:
lib/paperclip/storage/backblaze.rb

Overview

Defines a adapter to use store Paperclip attachments to Backblaze B2 Cloud Storage, which is similar to Amazon’s S3 service.

This allows you to use has_attached_file in your models with :storage => :backblaze.

Some required options include:

:storage - This should be set to :backblaze in order to use this
  storage adapter.

:b2_credentials - This should point to a YAML file containing your B2
  account ID, application key, and bucket. The contents should look
  something like:

  account_id: 123456789abc
  application_key: 0123456789abcdef0123456789abcdef0123456789
  bucket: my_b2_bucket_name

So for example, a model might be configured something like this:

class Note < ApplicationRecord
  has_attached_file :image,
    storage: :backblaze,
    b2_credentials: YAML.safe_load(ERB.new(File.read("#{Rails.root}/config/back_blaze.yml")).result)[Rails.env],
  ...

You can put the backblaze config in the environment config file e.g.:

# config/environments/production.rb

config.paperclip_defaults = {
  storage: :backblaze,
  b2_credentials: [Hash]
}

If you do it this way, then you don’t need to put it in the model.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/paperclip/storage/backblaze.rb', line 42

def self.extended(base)
  base.instance_eval do
    @b2_buckets = {}
    unless @options[:url] =~ /\Ab2.*url\z/
      @options[:url] = ':b2_path_url'.freeze
    end
  end

  unless Paperclip::Interpolations.respond_to? :b2_path_url
    Paperclip.interpolates(:b2_path_url) do |attachment, style|
      "#{attachment.cdn || ::Backblaze::B2.download_url}/file/#{attachment.b2_bucket_name}/#{attachment.path(style).sub(%r{\A/}, '')}"
    end
  end
end

Instance Method Details

#b2_bucketObject

Return the Backblaze::B2::Bucket object representing the bucket specified by the required options.



86
87
88
# File 'lib/paperclip/storage/backblaze.rb', line 86

def b2_bucket
  @b2_buckets[b2_bucket_name] ||= ::Backblaze::B2::Bucket.get_bucket(name: b2_bucket_name)
end

#b2_bucket_nameObject

Return the specified bucket name as a String.



91
92
93
94
# File 'lib/paperclip/storage/backblaze.rb', line 91

def b2_bucket_name
  
  @bucket_name ||= @options[:bucket] || b2_credentials.fetch(:bucket)
end

#b2_credentialsObject

Reads b2_credentials from the config file must be a hash

{
  account_id: 123456789abc
  application_key: 0123456789abcdef0123456789abcdef0123456789
}

Returns a Hash containing the parsed credentials.



68
69
70
# File 'lib/paperclip/storage/backblaze.rb', line 68

def b2_credentials
  @b2_credentials ||= @options.fetch(:b2_credentials)
end

#cdnObject



57
58
59
# File 'lib/paperclip/storage/backblaze.rb', line 57

def cdn
  @options[:cdn]
end

#copy_to_local_file(style, local_dest_path) ⇒ Object

(Internal)



134
135
136
137
138
139
140
# File 'lib/paperclip/storage/backblaze.rb', line 134

def copy_to_local_file(style, local_dest_path)
  ::File.open(local_dest_path, 'wb') do |local_file|
    file = get_file(filename: get_path(style))
    body = file.get(file.latest.download_url, parse: :plain)
    local_file.write(body)
  end
end

#exists?(style = default_style) ⇒ Boolean

Return whether this attachment exists in the bucket.

Returns:

  • (Boolean)


97
98
99
# File 'lib/paperclip/storage/backblaze.rb', line 97

def exists?(style = default_style)
  !get_file(filename: get_path(style)).nil?
end

#flush_deletesObject

(Internal) Used by Paperclip to remove remote files from storage.



125
126
127
128
129
130
131
# File 'lib/paperclip/storage/backblaze.rb', line 125

def flush_deletes
  @queued_for_delete.each do |path|
    file = get_file(filename: path.sub(%r{\A/}, ''))
    file.destroy! unless file.nil?
  end
  @queued_for_delete = []
end

#flush_writesObject

(Internal) Used by Paperclip to upload local files to storage.



115
116
117
118
119
120
121
122
# File 'lib/paperclip/storage/backblaze.rb', line 115

def flush_writes
  @queued_for_write.each do |style, file|
    base_name = ::File.dirname(get_path(style))
    name = ::File.basename(get_path(style))
    ::Backblaze::B2::File.create data: file, bucket: b2_bucket, name: name, base_name: base_name
  end
  @queued_for_write = {}
end

#get_file(filename:) ⇒ Object

Return a Backblaze::B2::File object representing the file named in the filename keyword, if it exists.



103
104
105
106
107
# File 'lib/paperclip/storage/backblaze.rb', line 103

def get_file(filename:)
  b2_bucket.file_names(first_file: filename, limit: 1).find do |f|
    f.file_name == filename
  end
end

#get_path(style = default_style) ⇒ Object

Return this attachment’s bucket file path as a String.



110
111
112
# File 'lib/paperclip/storage/backblaze.rb', line 110

def get_path(style = default_style)
  path(style).sub(%r{\A/}, '')
end

#loginObject

Authenticate with Backblaze with the account ID and secret key. This also caches several variables from the response related to the API, so it is important that it is executed at the very beginning.



75
76
77
78
79
80
81
82
# File 'lib/paperclip/storage/backblaze.rb', line 75

def 
  return if ::Backblaze::B2.token
  creds = b2_credentials
  ::Backblaze::B2.(
    account_id: creds.fetch(:account_id),
    application_key: creds.fetch(:application_key)
  )
end