| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| /// This library provides access to Google Cloud Storage. |
| /// |
| /// Google Cloud Storage is an object store for binary objects. Each |
| /// object has a set of metadata attached to it. For more information on |
| /// Google Cloud Storage see https://developers.google.com/storage/. |
| /// |
| /// There are two main concepts in Google Cloud Storage: Buckets and Objects. |
| /// A bucket is a container for objects and objects are the actual binary |
| /// objects. |
| /// |
| /// The API has two main classes for dealing with buckets and objects. |
| /// |
| /// The class `Storage` is the main API class providing access to working |
| /// with buckets. This is the 'bucket service' interface. |
| /// |
| /// The class `Bucket` provide access to working with objects in a specific |
| /// bucket. This is the 'object service' interface. |
| /// |
| /// Both buckets have objects, have names. The bucket namespace is flat and |
| /// global across all projects. This means that a bucket is always |
| /// addressable using its name without requiring further context. |
| /// |
| /// Within buckets the object namespace is also flat. Object are *not* |
| /// organized hierarchical. However, as object names allow the slash `/` |
| /// character this is often used to simulate a hierarchical structure |
| /// based on common prefixes. |
| /// |
| /// This package uses relative and absolute names to refer to objects. A |
| /// relative name is just the object name within a bucket, and requires the |
| /// context of a bucket to be used. A relative name just looks like this: |
| /// |
| /// object_name |
| /// |
| /// An absolute name includes the bucket name and uses the `gs://` prefix |
| /// also used by the `gsutil` tool. An absolute name looks like this. |
| /// |
| /// gs://bucket_name/object_name |
| /// |
| /// In most cases relative names are used. Absolute names are typically |
| /// only used for operations involving objects in different buckets. |
| /// |
| /// For most of the APIs in ths library which take instances of other classes |
| /// from this library it is the assumption that the actual implementations |
| /// provided here are used. |
| library; |
| |
| import 'dart:async'; |
| import 'dart:collection' show UnmodifiableListView, UnmodifiableMapView; |
| import 'dart:convert'; |
| import 'dart:typed_data'; |
| |
| import 'package:_discoveryapis_commons/_discoveryapis_commons.dart' as commons; |
| import 'package:googleapis/storage/v1.dart' as storage_api; |
| import 'package:http/http.dart' as http; |
| |
| import 'common.dart'; |
| import 'service_scope.dart' as ss; |
| |
| export 'common.dart'; |
| |
| part 'src/storage_impl.dart'; |
| |
| const Symbol _storageKey = #gcloud.storage; |
| |
| /// Access the [Storage] object available in the current service scope. |
| /// |
| /// The returned object will be the one which was previously registered with |
| /// [registerStorageService] within the current (or a parent) service scope. |
| /// |
| /// Accessing this getter outside of a service scope will result in an error. |
| /// See the `package:gcloud/service_scope.dart` library for more information. |
| Storage get storageService => ss.lookup(_storageKey) as Storage; |
| |
| /// Registers the [storage] object within the current service scope. |
| /// |
| /// The provided `storage` object will be available via the top-level |
| /// `storageService` getter. |
| /// |
| /// Calling this function outside of a service scope will result in an error. |
| /// Calling this function more than once inside the same service scope is not |
| /// allowed. |
| void registerStorageService(Storage storage) { |
| ss.register(_storageKey, storage); |
| } |
| |
| /// An ACL (Access Control List) describes access rights to buckets and |
| /// objects. |
| /// |
| /// An ACL is a prioritized sequence of access control specifications, |
| /// which individually prevent or grant access. |
| /// The access controls are described by [AclEntry] objects. |
| class Acl { |
| final List<AclEntry> _entries; |
| |
| /// The entries in the ACL. |
| List<AclEntry> get entries => UnmodifiableListView<AclEntry>(_entries); |
| |
| /// Create a new ACL with a list of ACL entries. |
| Acl(Iterable<AclEntry> entries) : _entries = List.from(entries); |
| |
| Acl._fromBucketAcl(storage_api.Bucket bucket) |
| : _entries = [ |
| for (final control |
| in bucket.acl ?? const <storage_api.BucketAccessControl>[]) |
| AclEntry(_aclScopeFromEntity(control.entity!), |
| _aclPermissionFromRole(control.role)) |
| ]; |
| |
| Acl._fromObjectAcl(storage_api.Object object) |
| : _entries = [ |
| for (final entry in object.acl ?? <storage_api.ObjectAccessControl>[]) |
| AclEntry(_aclScopeFromEntity(entry.entity!), |
| _aclPermissionFromRole(entry.role)), |
| ]; |
| |
| static AclScope _aclScopeFromEntity(String entity) { |
| if (entity.startsWith('user-')) { |
| var tmp = entity.substring(5); |
| var at = tmp.indexOf('@'); |
| if (at != -1) { |
| return AccountScope(tmp); |
| } else { |
| return StorageIdScope(tmp); |
| } |
| } else if (entity.startsWith('group-')) { |
| return GroupScope(entity.substring(6)); |
| } else if (entity.startsWith('domain-')) { |
| return DomainScope(entity.substring(7)); |
| } else if (entity.startsWith('allAuthenticatedUsers-')) { |
| return AclScope.allAuthenticated; |
| } else if (entity.startsWith('allUsers-')) { |
| return AclScope.allUsers; |
| } else if (entity.startsWith('project-')) { |
| var tmp = entity.substring(8); |
| var dash = tmp.indexOf('-'); |
| if (dash != -1) { |
| return ProjectScope(tmp.substring(dash + 1), tmp.substring(0, dash)); |
| } |
| } |
| return OpaqueScope(entity); |
| } |
| |
| static AclPermission _aclPermissionFromRole(String? role) { |
| if (role == 'READER') return AclPermission.READ; |
| if (role == 'WRITER') return AclPermission.WRITE; |
| if (role == 'OWNER') return AclPermission.FULL_CONTROL; |
| throw UnsupportedError( |
| "Server returned a unsupported permission role '$role'"); |
| } |
| |
| List<storage_api.BucketAccessControl> _toBucketAccessControlList() { |
| return _entries.map((entry) => entry._toBucketAccessControl()).toList(); |
| } |
| |
| List<storage_api.ObjectAccessControl> _toObjectAccessControlList() { |
| return _entries.map((entry) => entry._toObjectAccessControl()).toList(); |
| } |
| |
| @override |
| late final int hashCode = Object.hashAll(_entries); |
| |
| @override |
| bool operator ==(Object other) { |
| if (other is Acl) { |
| List entries = _entries; |
| List otherEntries = other._entries; |
| if (entries.length != otherEntries.length) return false; |
| for (var i = 0; i < entries.length; i++) { |
| if (entries[i] != otherEntries[i]) return false; |
| } |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| @override |
| String toString() => 'Acl($_entries)'; |
| } |
| |
| /// An ACL entry specifies that an entity has a specific access permission. |
| /// |
| /// A permission grants a specific permission to the entity. |
| class AclEntry { |
| final AclScope scope; |
| final AclPermission permission; |
| |
| AclEntry(this.scope, this.permission); |
| |
| storage_api.BucketAccessControl _toBucketAccessControl() { |
| var acl = storage_api.BucketAccessControl(); |
| acl.entity = scope._storageEntity; |
| acl.role = permission._storageBucketRole; |
| return acl; |
| } |
| |
| storage_api.ObjectAccessControl _toObjectAccessControl() { |
| var acl = storage_api.ObjectAccessControl(); |
| acl.entity = scope._storageEntity; |
| acl.role = permission._storageObjectRole; |
| return acl; |
| } |
| |
| @override |
| late final int hashCode = Object.hash(scope, permission); |
| |
| @override |
| bool operator ==(Object other) { |
| return other is AclEntry && |
| scope == other.scope && |
| permission == other.permission; |
| } |
| |
| @override |
| String toString() => 'AclEntry($scope, $permission)'; |
| } |
| |
| /// An ACL scope specifies an entity for which a permission applies. |
| /// |
| /// A scope can be one of: |
| /// |
| /// * Google Storage ID |
| /// * Google account email address |
| /// * Google group email address |
| /// * Google Apps domain |
| /// * Special identifier for all Google account holders |
| /// * Special identifier for all users |
| /// |
| /// See https://cloud.google.com/storage/docs/accesscontrol for more details. |
| abstract class AclScope { |
| /// ACL type for scope representing a Google Storage id. |
| static const int _typeStorageId = 0; |
| |
| /// ACL type for scope representing a project entity. |
| static const int _typeProject = 1; |
| |
| /// ACL type for scope representing an account holder. |
| static const int _typeAccount = 2; |
| |
| /// ACL type for scope representing a group. |
| static const int _typeGroup = 3; |
| |
| /// ACL type for scope representing a domain. |
| static const int _typeDomain = 4; |
| |
| /// ACL type for scope representing all authenticated users. |
| static const int _typeAllAuthenticated = 5; |
| |
| /// ACL type for scope representing all users. |
| static const int _typeAllUsers = 6; |
| |
| /// ACL type for scope representing an unsupported scope. |
| static const int _typeOpaque = 7; |
| |
| /// The id of the actual entity this ACL scope represents. The actual values |
| /// are set in the different subclasses. |
| final String _id; |
| |
| /// The type of this acope this ACL scope represents. |
| final int _type; |
| |
| /// ACL scope for all authenticated users. |
| static AllAuthenticatedScope allAuthenticated = AllAuthenticatedScope(); |
| |
| /// ACL scope for all users. |
| static AllUsersScope allUsers = AllUsersScope(); |
| |
| AclScope._(this._type, this._id); |
| |
| @override |
| late final int hashCode = Object.hash(_type, _id); |
| |
| @override |
| bool operator ==(Object other) { |
| return other is AclScope && _type == other._type && _id == other._id; |
| } |
| |
| @override |
| String toString() => 'AclScope($_storageEntity)'; |
| |
| String get _storageEntity; |
| } |
| |
| /// An ACL scope for an entity identified by a 'Google Storage ID'. |
| /// |
| /// The [storageId] is a string of 64 hexadecimal digits that identifies a |
| /// specific Google account holder or a specific Google group. |
| class StorageIdScope extends AclScope { |
| StorageIdScope(String storageId) |
| : super._(AclScope._typeStorageId, storageId); |
| |
| /// Google Storage ID. |
| String get storageId => _id; |
| |
| @override |
| String get _storageEntity => 'user-$_id'; |
| } |
| |
| /// An ACL scope for an entity identified by an individual email address. |
| class AccountScope extends AclScope { |
| AccountScope(String email) : super._(AclScope._typeAccount, email); |
| |
| /// Email address. |
| String get email => _id; |
| |
| @override |
| String get _storageEntity => 'user-$_id'; |
| } |
| |
| /// An ACL scope for an entity identified by an Google Groups email. |
| class GroupScope extends AclScope { |
| GroupScope(String group) : super._(AclScope._typeGroup, group); |
| |
| /// Group name. |
| String get group => _id; |
| |
| @override |
| String get _storageEntity => 'group-$_id'; |
| } |
| |
| /// An ACL scope for an entity identified by a domain name. |
| class DomainScope extends AclScope { |
| DomainScope(String domain) : super._(AclScope._typeDomain, domain); |
| |
| /// Domain name. |
| String get domain => _id; |
| |
| @override |
| String get _storageEntity => 'domain-$_id'; |
| } |
| |
| /// An ACL scope for an project related entity. |
| class ProjectScope extends AclScope { |
| /// Project role. |
| /// |
| /// Possible values are `owners`, `editors` and `viewers`. |
| final String role; |
| |
| ProjectScope(String project, this.role) |
| : super._(AclScope._typeProject, project); |
| |
| /// Project ID. |
| String get project => _id; |
| |
| @override |
| String get _storageEntity => 'project-$role-$_id'; |
| } |
| |
| /// An ACL scope for an unsupported scope. |
| class OpaqueScope extends AclScope { |
| OpaqueScope(String id) : super._(AclScope._typeOpaque, id); |
| |
| @override |
| String get _storageEntity => _id; |
| } |
| |
| /// ACL scope for a all authenticated users. |
| class AllAuthenticatedScope extends AclScope { |
| AllAuthenticatedScope() : super._(AclScope._typeAllAuthenticated, 'invalid'); |
| |
| @override |
| String get _storageEntity => 'allAuthenticatedUsers'; |
| } |
| |
| /// ACL scope for a all users. |
| class AllUsersScope extends AclScope { |
| AllUsersScope() : super._(AclScope._typeAllUsers, 'invalid'); |
| |
| @override |
| String get _storageEntity => 'allUsers'; |
| } |
| |
| /// Permissions for individual scopes in an ACL. |
| class AclPermission { |
| /// Provide read access. |
| // ignore: constant_identifier_names |
| static const READ = AclPermission._('READER'); |
| |
| /// Provide write access. |
| /// |
| /// For objects this permission is the same as [FULL_CONTROL]. |
| // ignore: constant_identifier_names |
| static const WRITE = AclPermission._('WRITER'); |
| |
| /// Provide full control. |
| /// |
| /// For objects this permission is the same as [WRITE]. |
| // ignore: constant_identifier_names |
| static const FULL_CONTROL = AclPermission._('OWNER'); |
| |
| final String _id; |
| |
| const AclPermission._(this._id); |
| |
| String get _storageBucketRole => _id; |
| |
| String get _storageObjectRole => this == WRITE ? FULL_CONTROL._id : _id; |
| |
| @override |
| int get hashCode => _id.hashCode; |
| |
| @override |
| bool operator ==(Object other) { |
| return other is AclPermission && _id == other._id; |
| } |
| |
| @override |
| String toString() => 'AclPermission($_id)'; |
| } |
| |
| /// Definition of predefined ACLs. |
| /// |
| /// There is a convenient way of referring to number of _predefined_ ACLs. These |
| /// predefined ACLs have explicit names, and can _only_ be used to set an ACL, |
| /// when either creating or updating a bucket or object. This set of predefined |
| /// ACLs are expanded on the server to their actual list of [AclEntry] objects. |
| /// When information is retrieved on a bucket or object, this expanded list will |
| /// be present. For a description of these predefined ACLs see: |
| /// https://cloud.google.com/storage/docs/accesscontrol#extension. |
| class PredefinedAcl { |
| final String _name; |
| const PredefinedAcl._(this._name); |
| |
| /// Predefined ACL for the 'authenticated-read' ACL. Applies to both buckets |
| /// and objects. |
| static const PredefinedAcl authenticatedRead = |
| PredefinedAcl._('authenticatedRead'); |
| |
| /// Predefined ACL for the 'private' ACL. Applies to both buckets |
| /// and objects. |
| static const PredefinedAcl private = PredefinedAcl._('private'); |
| |
| /// Predefined ACL for the 'project-private' ACL. Applies to both buckets |
| /// and objects. |
| static const PredefinedAcl projectPrivate = PredefinedAcl._('projectPrivate'); |
| |
| /// Predefined ACL for the 'public-read' ACL. Applies to both buckets |
| /// and objects. |
| static const PredefinedAcl publicRead = PredefinedAcl._('publicRead'); |
| |
| /// Predefined ACL for the 'public-read-write' ACL. Applies only to buckets. |
| static const PredefinedAcl publicReadWrite = |
| PredefinedAcl._('publicReadWrite'); |
| |
| /// Predefined ACL for the 'bucket-owner-full-control' ACL. Applies only to |
| /// objects. |
| static const PredefinedAcl bucketOwnerFullControl = |
| PredefinedAcl._('bucketOwnerFullControl'); |
| |
| /// Predefined ACL for the 'bucket-owner-read' ACL. Applies only to |
| /// objects. |
| static const PredefinedAcl bucketOwnerRead = |
| PredefinedAcl._('bucketOwnerRead'); |
| |
| @override |
| String toString() => 'PredefinedAcl($_name)'; |
| } |
| |
| /// Information on a bucket. |
| abstract class BucketInfo { |
| /// Name of the bucket. |
| String get bucketName; |
| |
| /// Entity tag for the bucket. |
| String get etag; |
| |
| /// When this bucket was created. |
| DateTime get created; |
| |
| /// Bucket ID. |
| String get id; |
| |
| /// Acl of the bucket. |
| Acl get acl; |
| } |
| |
| /// Access to Cloud Storage |
| abstract class Storage { |
| /// List of required OAuth2 scopes for Cloud Storage operation. |
| // ignore: constant_identifier_names |
| static const List<String> SCOPES = <String>[ |
| storage_api.StorageApi.devstorageFullControlScope |
| ]; |
| |
| /// Initializes access to cloud storage. |
| factory Storage(http.Client client, String project) = _StorageImpl; |
| |
| /// Create a cloud storage bucket. |
| /// |
| /// Creates a cloud storage bucket named [bucketName]. |
| /// |
| /// The bucket ACL can be set by passing [predefinedAcl] or [acl]. If both |
| /// are passed the entries from [acl] with be followed by the expansion of |
| /// [predefinedAcl]. |
| /// |
| /// Returns a [Future] which completes when the bucket has been created. |
| Future createBucket(String bucketName, |
| {PredefinedAcl? predefinedAcl, Acl? acl}); |
| |
| /// Delete a cloud storage bucket. |
| /// |
| /// Deletes the cloud storage bucket named [bucketName]. |
| /// |
| /// If the bucket is not empty the operation will fail. |
| /// |
| /// The returned [Future] completes when the operation is finished. |
| Future deleteBucket(String bucketName); |
| |
| /// Access bucket object operations. |
| /// |
| /// Instantiates a `Bucket` object referring to the bucket named [bucketName]. |
| /// |
| /// When an object is created using the resulting `Bucket` an ACL will always |
| /// be set. If the object creation does not pass any explicit ACL information |
| /// a default ACL will be used. |
| /// |
| /// If the arguments [defaultPredefinedObjectAcl] or [defaultObjectAcl] are |
| /// passed they define the default ACL. If both are passed the entries from |
| /// [defaultObjectAcl] with be followed by the expansion of |
| /// [defaultPredefinedObjectAcl] when an object is created. |
| /// |
| /// Otherwise the default object ACL attached to the bucket will be used. |
| /// |
| /// Returns a `Bucket` instance. |
| Bucket bucket(String bucketName, |
| {PredefinedAcl? defaultPredefinedObjectAcl, Acl? defaultObjectAcl}); |
| |
| /// Check whether a cloud storage bucket exists. |
| /// |
| /// Checks whether the bucket named [bucketName] exists. |
| /// |
| /// Returns a [Future] which completes with `true` if the bucket exists. |
| Future<bool> bucketExists(String bucketName); |
| |
| /// Get information on a bucket |
| /// |
| /// Provide metadata information for bucket named [bucketName]. |
| /// |
| /// Returns a [Future] which completes with a `BucketInfo` object. |
| Future<BucketInfo> bucketInfo(String bucketName); |
| |
| /// List names of all buckets. |
| /// |
| /// Returns a [Stream] of bucket names. |
| Stream<String> listBucketNames(); |
| |
| /// Start paging through names of all buckets. |
| /// |
| /// The maximum number of buckets in each page is specified in [pageSize]. |
| /// |
| /// Returns a [Future] which completes with a `Page` object holding the |
| /// first page. Use the `Page` object to move to the next page of buckets. |
| Future<Page<String>> pageBucketNames({int pageSize = 50}); |
| |
| /// Copy an object. |
| /// |
| /// Copy object [src] to object [dest]. |
| /// |
| /// The names of [src] and [dest] must be absolute. |
| Future copyObject(String src, String dest); |
| } |
| |
| /// Information on a specific object. |
| /// |
| /// This class provides access to information on an object. This includes |
| /// both the properties which are provided by Cloud Storage (such as the |
| /// MD5 hash) and the properties which can be changed (such as content type). |
| /// |
| /// The properties provided by Cloud Storage are direct properties on this |
| /// object. |
| /// |
| /// The mutable properties are properties on the `metadata` property. |
| abstract class ObjectInfo { |
| /// Name of the object. |
| String get name; |
| |
| /// Length of the data. |
| int get length; |
| |
| /// When this object was updated. |
| DateTime get updated; |
| |
| /// Entity tag for the object. |
| String get etag; |
| |
| /// MD5 hash of the object. |
| List<int> get md5Hash; |
| |
| /// CRC32c checksum, as described in RFC 4960. |
| int get crc32CChecksum; |
| |
| /// URL for direct download. |
| Uri get downloadLink; |
| |
| /// Object generation. |
| ObjectGeneration get generation; |
| |
| /// Additional metadata. |
| ObjectMetadata get metadata; |
| } |
| |
| /// Generational information on an object. |
| class ObjectGeneration { |
| /// Object generation. |
| final String objectGeneration; |
| |
| /// Metadata generation. |
| final int metaGeneration; |
| |
| const ObjectGeneration(this.objectGeneration, this.metaGeneration); |
| } |
| |
| /// Access to object metadata. |
| abstract class ObjectMetadata { |
| factory ObjectMetadata( |
| {Acl? acl, |
| String? contentType, |
| String? contentEncoding, |
| String? cacheControl, |
| String? contentDisposition, |
| String? contentLanguage, |
| Map<String, String>? custom}) = _ObjectMetadata; |
| |
| /// ACL. |
| Acl? get acl; |
| |
| /// `Content-Type` for this object. |
| String? get contentType; |
| |
| /// `Content-Encoding` for this object. |
| String? get contentEncoding; |
| |
| /// `Cache-Control` for this object. |
| String? get cacheControl; |
| |
| /// `Content-Disposition` for this object. |
| String? get contentDisposition; |
| |
| /// `Content-Language` for this object. |
| /// |
| /// The value of this field must confirm to RFC 3282. |
| String? get contentLanguage; |
| |
| /// Custom metadata. |
| Map<String, String>? get custom; |
| |
| /// Create a copy of this object with some values replaced. |
| /// |
| // TODO: This cannot be used to set values to null. |
| ObjectMetadata replace( |
| {Acl? acl, |
| String? contentType, |
| String? contentEncoding, |
| String? cacheControl, |
| String? contentDisposition, |
| String? contentLanguage, |
| Map<String, String>? custom}); |
| } |
| |
| /// Result from List objects in a bucket. |
| /// |
| /// Listing operate like a directory listing, despite the object |
| /// namespace being flat. |
| /// |
| /// See [Bucket.list] for information on how the hierarchical structure |
| /// is determined. |
| class BucketEntry { |
| /// Whether this is information on an object. |
| final bool isObject; |
| |
| /// Name of object or directory. |
| final String name; |
| |
| BucketEntry._object(this.name) : isObject = true; |
| |
| BucketEntry._directory(this.name) : isObject = false; |
| |
| /// Whether this is a prefix. |
| bool get isDirectory => !isObject; |
| } |
| |
| /// Access to operations on a specific cloud storage bucket. |
| abstract class Bucket { |
| /// Name of this bucket. |
| String get bucketName; |
| |
| /// Absolute name of an object in this bucket. This includes the gs:// prefix. |
| String absoluteObjectName(String objectName); |
| |
| /// Create a new object. |
| /// |
| /// Create an object named [objectName] in the bucket. |
| /// |
| /// If an object named [objectName] already exists this object will be |
| /// replaced. |
| /// |
| /// If the length of the data to write is known in advance this can be passed |
| /// as [length]. This can help to optimize the upload process. |
| /// |
| /// Additional metadata on the object can be passed either through the |
| /// `metadata` argument or through the specific named arguments |
| /// (such as `contentType`). Values passed through the specific named |
| /// arguments takes precedence over the values in `metadata`. |
| /// |
| /// If [contentType] is not passed the default value of |
| /// `application/octet-stream` will be used. |
| /// |
| /// It is possible to at one of the predefined ACLs on the created object |
| /// using the [predefinedAcl] argument. If the [metadata] argument contain a |
| /// ACL as well, this ACL with be followed by the expansion of |
| /// [predefinedAcl]. |
| /// |
| /// Returns a `StreamSink` where the object content can be written. When |
| /// The object content has been written the `StreamSink` completes with |
| /// an `ObjectInfo` instance with the information on the object created. |
| StreamSink<List<int>> write(String objectName, |
| {int? length, |
| ObjectMetadata? metadata, |
| Acl? acl, |
| PredefinedAcl? predefinedAcl, |
| String? contentType}); |
| |
| /// Create an new object in the bucket with specified content. |
| /// |
| /// Writes [bytes] to the created object. |
| /// |
| /// See [write] for more information on the additional arguments. |
| /// |
| /// Returns a `Future` which completes with an `ObjectInfo` instance when |
| /// the object is written. |
| Future<ObjectInfo> writeBytes(String name, List<int> bytes, |
| {ObjectMetadata? metadata, |
| Acl? acl, |
| PredefinedAcl? predefinedAcl, |
| String? contentType}); |
| |
| /// Read object content as byte stream. |
| /// |
| /// If [offset] is provided, [length] must also be provided. |
| /// |
| /// If [length] is provided, it must be greater than `0`. |
| /// |
| /// If there is a problem accessing the file, a [DetailedApiRequestError] is |
| /// thrown. |
| Stream<List<int>> read(String objectName, {int? offset, int? length}); |
| |
| /// Lookup object metadata. |
| /// |
| // TODO: More documentation |
| Future<ObjectInfo> info(String name); |
| |
| /// Delete an object. |
| /// |
| // TODO: More documentation |
| Future delete(String name); |
| |
| /// Update object metadata. |
| /// |
| // TODO: More documentation |
| Future updateMetadata(String objectName, ObjectMetadata metadata); |
| |
| /// List objects in the bucket. |
| /// |
| /// Listing operates like a directory listing, despite the object |
| /// namespace being flat. Unless [delimiter] is specified, the character `/` |
| /// is being used to separate object names into directory components. |
| /// To list objects recursively, the [delimiter] can be set to empty string. |
| /// |
| /// Retrieves a list of objects and directory components starting |
| /// with [prefix]. |
| /// |
| /// Returns a [Stream] of [BucketEntry]. Each element of the stream |
| /// represents either an object or a directory component. |
| Stream<BucketEntry> list({String? prefix, String? delimiter}); |
| |
| /// Start paging through objects in the bucket. |
| /// |
| /// The maximum number of objects in each page is specified in [pageSize]. |
| /// |
| /// See [list] for more information on the other arguments. |
| /// |
| /// Returns a `Future` which completes with a `Page` object holding the |
| /// first page. Use the `Page` object to move to the next page. |
| Future<Page<BucketEntry>> page( |
| {String? prefix, String? delimiter, int pageSize = 50}); |
| } |