view release on metacpan or search on metacpan
# if you would rather download with the 84-character GUID
my $response = $b2->b2_download_file_by_id(
file_id => 'X-Bz-File-Id GUID from above',
save_to_location => '/opt/majestica/tmp'
);
# For all of these $response is the output from the B2 V4 API
# to confirm all is well
my $all_is_well = $b2->current_status_is_not_ok != 1;
# or
my $all_is_well = $b2->current_status_is_ok());
# to get the latest error
print $b2->latest_error();
# if none, will be 'No error message found'
# DESCRIPTION / SET UP
This module should help you create buckets and store/retrieve files in the
lib/Backblaze/B2V4.pm view on Meta::CPAN
use HTTP::Tiny;
use MIME::Base64;
use Path::Tiny;
use URI::Escape;
use Types::Common -all;
use Marlin::Util -all;
use Marlin
'application_key_id' => { is => 'ro', isa => 'NonEmptyStr' },
'application_key' => { is => 'ro', isa => 'NonEmptyStr' },
'current_status_is_not_ok' => { is => 'rw', isa => 'Bool', default => 0 },
'login_error' => { is => 'rw', isa => 'Bool', default => 0 },
'errors' => { is => 'rw', isa => 'ArrayRef', default => [] },
'api_info' => { is => 'rw', isa => 'HashRef', builder => 'build_api_info' },
'bucket_info' => { is => 'rw', isa => 'HashRef', default => {} },
'file_info' => { is => 'rw', isa => 'HashRef', default => {} },
;
# builder method to create api_info hashref attribute
sub build_api_info ($self) {
my $response = $self->send_request(
lib/Backblaze/B2V4.pm view on Meta::CPAN
$error_message = 'Error: ' . $response->{reason};
}
# track the error / set current state
return $self->error_tracker(
'error_message' => $error_message . ' (' . $response->{status} . ')',
'url' => $args->url,
);
}
$self->current_status_is_not_ok(0);
return $b2_response;
}
# indicate if everything is fine
sub current_status_is_ok ($self) {
return !$self->current_status_is_not_ok;
}
# for tracking errors into $self->{errrors}[];
signature_for error_tracker => (
method => true,
named => [
error_message => Str,
url => Str,
],
returns => Bool,
);
sub error_tracker ($self, $args) {
push(@{ $self->errors }, {
'error_message' => $args->error_message,
'url' => $args->url,
});
$self->current_status_is_not_ok(1);
return 0;
}
# please tell me the lastest error message
sub latest_error ($self) {
my $latest_error = $self->errors->[-1];
if (!$latest_error || !$latest_error->{error_message}) {
return 'No error message found';
}
lib/Backblaze/B2V4.pm view on Meta::CPAN
save_to_location => Str, { optional => true },
],
returns => Bool|HashRef,
);
sub b2_download_file_by_id ($self, $args) {
my $response = $self->send_request(
'url' => $self->api_info->{download_url} . '/b2api/v4/b2_download_file_by_id' . '?fileId=' . $args->file_id,
);
if ($self->current_status_is_not_ok) {
return 0;
}
# if they provided a save-to location (a directory) and the file was found, let's save it out
if ($args->save_to_location) {
$self->save_downloaded_file(
save_to_location => $args->save_to_location,
response => $response
);
}
lib/Backblaze/B2V4.pm view on Meta::CPAN
);
sub b2_download_file_by_name ($self, $args) {
# send the request, as a GET
my $response = $self->send_request(
'url' => $self->api_info->{download_url} . '/file/' . uri_escape($args->bucket_name) . '/' . uri_escape($args->file_name),
);
# if the file was found, you will have the relevant headers in $response
# as well as the file's contents in $response->{file_contents}
if ($self->current_status_is_not_ok) {
return 0;
}
# if they provided a save-to location (a directory) and the file was found, let's save it out
if ($args->save_to_location) {
$self->save_downloaded_file(
save_to_location => $args->save_to_location,
response => $response
);
}
lib/Backblaze/B2V4.pm view on Meta::CPAN
'url' => $upload_info->{upload_url},
'authorization' => $upload_info->{authorization_token},
'file_contents' => $file_contents,
'headers' => {
'X-Bz-File-Name' => uri_escape( $new_file_name ),
'X-Bz-Content-Sha1' => sha1_hex( $file_contents ),
'Content-Type' => $content_type,
},
);
return $self->current_status_is_not_ok ? 0 : $response->{fileId};
}
# method to get the information needed to upload into a specific B2 bucket
signature_for b2_get_upload_info => (
method => true,
named => [
bucket_name => NonEmptyStr,
],
returns => HashRef|Bool,
);
lib/Backblaze/B2V4.pm view on Meta::CPAN
if ($args->bucket_name) {
$post_params->{bucketName} = $args->bucket_name;
}
# send the request
my $response = $self->send_request(
'url' => 'b2_list_buckets',
'post_params' => $post_params,
);
if ($self->current_status_is_not_ok) {
return 0;
}
# if we succeeded, load in all the found buckets to $self->{buckets}
# that will be a hash of info, keyed by name
my $bucket_name;
foreach my $bucket_info (@{ $response->{buckets} }) {
$bucket_name = $bucket_info->{bucketName};
$self->bucket_info->{$bucket_name} = {
lib/Backblaze/B2V4.pm view on Meta::CPAN
'bucket_type' => $bucket_info->{bucketType},
};
}
# if that bucket was not found, maybe they want to go ahead and create it?
$bucket_name = $args->bucket_name;
if ($bucket_name && !$self->bucket_info->{$bucket_name}->{bucket_id} && $args->auto_create_bucket) {
$self->b2_bucket_maker(
bucket_name => $bucket_name
);
if ($self->current_status_is_not_ok) {
return 0;
}
# this will call back to me and get the info
}
return 1;
}
# method to retrieve file names / info from a bucket
# this client library is bucket-name-centric, so it looks for the bucket name as a arg
lib/Backblaze/B2V4.pm view on Meta::CPAN
if ($args->start_file_name) {
$post_params->{startFileName} = $args->start_file_name;
}
my $response = $self->send_request(
'url' => 'b2_list_file_names',
'post_params' => $post_params,
);
# if we succeeded, read in the files
if ($self->current_status_is_not_ok) {
return 0;
}
$self->bucket_info->{$bucket_name}->{next_file_name} = $response->{nextFileName};
# add to our possibly-started array of file info for this bucket
push(
@{ $self->{buckets}{$bucket_name}{files} },
@{ $response->{files} }
);
lib/Backblaze/B2V4.pm view on Meta::CPAN
if ($self->file_info->{$file_id} && ref($self->file_info->{$file_id}) eq 'HASH') {
return $self->file_info->{$file_id};
}
# retrieve the file information
my $response = $self->send_request(
'url' => 'b2_get_file_info?fileId=' . $file_id,
);
if ($self->current_status_is_not_ok) {
return 0;
}
# i am not going to waste the CPU cycles de-camelizing these sub-keys
$self->file_info->{$file_id} = $response;
return $response;
}
# method to create a bucket
lib/Backblaze/B2V4.pm view on Meta::CPAN
'algorithm' => 'AES256',
};
}
# create the bucket...
my $response = $self->send_request(
'url' => 'b2_create_bucket',
'post_params' => $post_params,
);
if ($self->current_status_is_not_ok) {
return 0;
}
# otherwise successful, stash our new bucket into $self->{buckets}
$self->bucket_info->{$args->bucket_name} = {
'bucket_id' => $response->{bucketId},
'bucket_type' => 'allPrivate',
};
return 1;
lib/Backblaze/B2V4.pm view on Meta::CPAN
# send the request
$self->send_request(
'url' => 'b2_delete_bucket',
'post_params' => {
'accountId' => $self->api_info->account_id,
'bucketId' => $bucket_id,
},
);
return $self->current_status_is_not_ok ? 0 : 1;
}
# method to delete a stored file object. B2 thinks of these as 'versions,'
# but if you use unique names, one version = one file
signature_for b2_delete_file_version => (
method => true,
named => [
file_name => NonEmptyStr,
file_id => NonEmptyStr,
],
lib/Backblaze/B2V4.pm view on Meta::CPAN
sub b2_delete_file_version ($self, $args) {
# send the request
$self->send_request(
'url' => 'b2_delete_file_version',
'post_params' => {
'fileName' => $args->file_name,
'fileId' => $args->file_id,
},
);
return $self->current_status_is_not_ok ? 0 : 1;
}
# method to upload a large file (>100MB)
signature_for b2_upload_large_file => (
method => true,
named => [
new_file_name => NonEmptyStr,
bucket_name => NonEmptyStr,
file_location => NonEmptyStr,
content_type => NonEmptyStr, { optional => true, default => 'b2/x-auto' },
lib/Backblaze/B2V4.pm view on Meta::CPAN
# and tell B2
$response = $self->send_request(
'url' => 'b2_finish_large_file',
'post_params' => {
'fileId' => $large_file_id,
'partSha1Array' => \@sha1_array,
},
);
# phew, i'm tired...
return $self->current_status_is_not_ok ? 0 : $response->{fileId};
}
1;
__END__
=head1 NAME
Backblaze::B2V4 - Client library for the Backblaze B2 Cloud Storage Service V4 API.
lib/Backblaze/B2V4.pm view on Meta::CPAN
# if you would rather download with the 84-character GUID
my $response = $b2->b2_download_file_by_id(
file_id => 'X-Bz-File-Id GUID from above',
save_to_location => '/opt/majestica/tmp'
);
# For all of these $response is the output from the B2 V4 API
# to confirm all is well
my $all_is_well = $b2->current_status_is_not_ok != 1;
# or
my $all_is_well = $b2->current_status_is_ok());
# to get the latest error
print $b2->latest_error();
# if none, will be 'No error message found'
=head1 DESCRIPTION / SET UP
This module should help you create buckets and store/retrieve files in the
lib/Backblaze/B2V4.pm view on Meta::CPAN
See: https://www.backblaze.com/b2/docs/b2_get_upload_info.html
=head2 send_request
send_request() handles all the communications with B2.
You should be able to use this to make calls not explicitly
provided by this library.
If send_request() gets a 200 HTTP status from B2, then the call went
great, $b2->current_status_is_not_ok will be 0, and
the JSON response will be returned.
If a 200 is not received from B2, $b2->current_status_is_not_ok
will be 1, and you can find an error in $b2->latest_error()
Note that the base URL for this API session will be stored
under $b2->api_info->{api_url} so that you build a URL like so:
$list_buckets_url = $b2->api_info->{api_url}.'/b2api/v4/b2_list_buckets';
Example of a GET API request:
my $response = $b2->send_request(
script/b2_client view on Meta::CPAN
if ($b2->login_error) {
die "ERROR: The B2 API keys you provided did not authenticate. Please verify and try again.\n";
}
return $b2;
}
sub show_result {
my ($b2, $result_message) = @_;
if ($b2->current_status_is_not_ok) {
return get_error_message($b2);
}
return "\n" . $result_message . "\n";
}
sub get_error_message {
my ($b2) = @_;
if ($b2->latest_error() !~ /^Error/) {