Skip to content

Latest commit

 

History

History
457 lines (367 loc) · 14.1 KB

README_EN.md

File metadata and controls

457 lines (367 loc) · 14.1 KB

Language: 中文简体 | English

flutter_oss_aliyun

Oss aliyun plugin for flutter. Use sts policy to authenticate the user.

flutter pub: https://pub.dev/packages/flutter_oss_aliyun

oss sts document: https://help.aliyun.com/document_detail/100624.html

🐱  Init Client

First, add flutter_oss_aliyun as a dependency in your pubspec.yaml file.

dependencies:
  flutter_oss_aliyun: ^6.4.2

Don't forget to flutter pub get.

Init the client, we provide two ways to do it

1. Use sts server api: provide the sts url from our backend server

Client.init(
    stsUrl: "server url get sts token",
    ossEndpoint: "oss-cn-beijing.aliyuncs.com",
    bucketName: "bucket name",
);

This sts url api at least return the data:

{
  "AccessKeyId": "AccessKeyId",
  "AccessKeySecret": "AccessKeySecret",
  "SecurityToken": "SecurityToken",
  "Expiration": "2022-03-22T11:33:06Z"
}

2. use authGetter

Client.init(
    ossEndpoint: "oss-cn-beijing.aliyuncs.com",
    bucketName: "bucketName",
    authGetter: _authGetter
);

Auth _authGetter() {
  return Auth(
      accessKey: "accessKey",
      accessSecret: 'accessSecret',
      expire: '2023-02-23T14:02:46Z',
      secureToken: 'token',
  );
}

Integrate with get_it

injectable: https://pub.dev/packages/injectable

@module
abstract class OssProvider {
  @singleton
  Client client() {
    return Client.init(
      stsUrl: Env.stsUrl,
      ossEndpoint: Env.endpointUrl,
      bucketName: Env.bucketName,
    );
  }
}

customize the dio

you can pass the dio in init method to use your own Dio.

Client.init(
    stsUrl: "server url get sts token",
    ossEndpoint: "oss-cn-beijing.aliyuncs.com",
    bucketName: "bucket name",
    dio: Dio(BaseOptions(connectTimeout: 9000)),
);

🎨 Usage

put the object to oss with progress callback

callback reference: https://help.aliyun.com/document_detail/31989.htm?spm=a2c4g.11186623.0.0.73a830ffn45LMY#reference-zkm-311-hgb

final bytes = "file bytes".codeUnits;

await Client().putObject(
  bytes,
  "test.txt",
  option: PutRequestOption(
    onSendProgress: (count, total) {
      print("send: count = $count, and total = $total");
    },
    onReceiveProgress: (count, total) {
      print("receive: count = $count, and total = $total");
    },
    override: false,
    aclModel: AclMode.publicRead,
    storageType: StorageType.ia,
    headers: {"cache-control": "no-cache"},
    callback: Callback(
      callbackUrl: "callback url",
      callbackBody: "{\"mimeType\":\${mimeType}, \"filepath\":\${object},\"size\":\${size},\"bucket\":\${bucket},\"phone\":\${x:phone}}",
      callbackVar: {"x:phone": "android"},
      calbackBodyType: CalbackBodyType.json,
    ),    
  ),
);

PutRequestOption, fields are optional

Filed Default value Description
override true true: Allow override the same name Object
false: Not allow override the same name Object
aclModel inherited 1. publicWrite: Anyone (including anonymous visitors) can read and write about the Object
2. publicRead: Only the owner of the Object can write to the Object, and anyone (including anonymous visitors) can read the Object
3. private: Only the owner of the Object can read and write to the Object, and no one else can access the Object
4. inherited: This Object follows the read and write permission of Bucket, which is what is Bucket and Object is what permission
reference: https://help.aliyun.com/document_detail/100676.htm?spm=a2c4g.11186623.0.0.56637952SnxOWV#concept-blw-yqm-2gb
storageType Standard reference: https://help.aliyun.com/document_detail/51374.htm?spm=a2c4g.11186623.0.0.56632b55htpEQX#concept-fcn-3xt-tdb

append object

final Response<dynamic> resp = await Client().appendObject(
  Uint8List.fromList(utf8.encode("Hello World")),
  "test_append.txt",
);

final Response<dynamic> resp2 = await Client().appendObject(
  position: int.parse(resp.headers["x-oss-next-append-position"]?[0]),
  Uint8List.fromList(utf8.encode(", Fluter.")),
  "test_append.txt",
);

copy object

final Response<dynamic> resp = await Client().copyObject(
  const CopyRequestOption(
    sourceFileKey: 'test.csv',
    targetFileKey: "test_copy.csv",
    targetBucketName: "bucket_2"
  ),
);

cancel file upload

final CancelToken cancelToken = CancelToken();
final bytes = ("long long bytes" * 1000).codeUnits;

Client().putObject(
  Uint8List.fromList(utf8.encode(string)),
  "cancel_token_test.txt",
  cancelToken: cancelToken,
  option: PutRequestOption(
    onSendProgress: (count, total) {
      if (kDebugMode) {
        print("send: count = $count, and total = $total");
      }
      if (count > 56) {
        cancelToken.cancel("cancel the uploading.");
      }
    },
  ),
).then((response) {
  // success
  print("upload success = ${response.statusCode}");
}).catchError((err) {
  if (CancelToken.isCancel(err)) {
    print("error message = ${err.message}");
  } else {
    // handle other errors
  }
});

batch put the object to oss

await Client().putObjects([
  AssetEntity(
    filename: "filename1.txt",
    bytes: "files1".codeUnits,
    option: PutRequestOption(
      onSendProgress: (count, total) {
        print("send: count = $count, and total = $total");
      },
      onReceiveProgress: (count, total) {
        print("receive: count = $count, and total = $total");
      },
      aclModel: AclMode.private,
    ),
  ),
  AssetEntity(filename: "filename2.txt", bytes: "files2".codeUnits),
]);

update object from local file

final Response<dynamic> resp = await Client().putObjectFile(
  "/Users/aaa.pdf",
  fileKey: "aaa.png",
  option: PutRequestOption(
    onSendProgress: (count, total) {
      print("send: count = $count, and total = $total");
    },
    onReceiveProgress: (count, total) {
      print("receive: count = $count, and total = $total");
    },
    aclModel: AclMode.private,
    callback: Callback(
      callbackUrl: callbackUrl,
      callbackBody:
          "{\"mimeType\":\${mimeType}, \"filepath\":\${object},\"size\":\${size},\"bucket\":\${bucket},\"phone\":\${x:phone}}",
      callbackVar: {"x:phone": "android"},
      calbackBodyType: CalbackBodyType.json,
    ),
  ),
);

batch upload local files to oss

final List<Response<dynamic>> resp = await Client().putObjectFiles(
  [
    AssetFileEntity(
      filepath: "//Users/private.txt",
      option: PutRequestOption(
        onSendProgress: (count, total) {
          print("send: count = $count, and total = $total");
        },
        onReceiveProgress: (count, total) {
          print("receive: count = $count, and total = $total");
        },
        override: false,
        aclModel: AclMode.private,
      ),
    ),
    AssetFileEntity(
      filepath: "//Users/splash.png",
      filename: "aaa.png",
      option: PutRequestOption(
        onSendProgress: (count, total) {
          print("send: count = $count, and total = $total");
        },
        onReceiveProgress: (count, total) {
          print("receive: count = $count, and total = $total");
        },
        override: true,
      ),
    ),
  ],
);

get the object from oss with progress callback

await Client().getObject(
  "test.txt",
  onReceiveProgress: (count, total) {
    debugPrint("received = $count, total = $total");
  },
);

does the object existed

final bool isExisted = await Client().doesObjectExist(
    "aaa.jpg",
);

download the object from oss with progress callback

await Client().downloadObject(
  "test.txt", 
  "./example/test.txt",
  onReceiveProgress: (count, total) {
    debugPrint("received = $count, total = $total");
  },
);

delete the object from oss

await Client().deleteObject("test.txt");

batch delete the object from oss

await Client().deleteObjects(["filename1.txt", "filename2.txt"]);

get signed url that can be accessed in browser directly

This is not safe due to the url include the security-token information even it will expire in short time. Use it carefully!!!

final String url = await Client().getSignedUrl(
  "test.jpg",
  params: {"x-oss-process": "image/resize,w_10/quality,q_90"},
);

get multiple signed urls

This is not safe due to the url include the security-token information even it will expire in short time. Use it carefully!!!

final Map<String, String> result = await Client().getSignedUrls(["test.txt", "filename1.txt"]);

list buckets

list all owned buckets, refer to: https://help.aliyun.com/document_detail/31957.html

final Response<dynamic> resp = await Client().listBuckets({"max-keys": 2});

list objects

List the information of all files (Object) in the storage space (Bucket). The parameters and response, refer to: https://help.aliyun.com/document_detail/187544.html

final Response<dynamic> resp = await Client().listFiles({});

get bucket info

View bucket information, The response refer to: https://help.aliyun.com/document_detail/31968.html

final Response<dynamic> resp = await Client().getBucketInfo();

get objects counts and bucket details

Gets the storage capacity of the specified storage space (Bucket) and the number of files (Object), The response refer to: https://help.aliyun.com/document_detail/426056.html

final Response<dynamic> resp = await Client().getBucketStat();

get object metadata

final Response<dynamic> resp = await Client().getObjectMeta("huhx.csv");

query regions

  • find all
final Response<dynamic> resp = await Client().getAllRegions();
  • find by name
final Response<dynamic> resp = await Client().getRegion("oss-ap-northeast-1");

bucket acl

  • query
final Response<dynamic> resp = await Client().getBucketAcl(
  bucketName: "bucket-name",
);
  • add or update
final Response<dynamic> resp = await Client().putBucketAcl(
  AciMode.publicRead, 
  bucketName: "bucket-name",
);

bucket policy

  • query
final Response<dynamic> resp = await Client().getBucketPolicy(
  bucketName: "bucket-name",
);
  • update
final Response<dynamic> resp = await Client().putBucketPolicy(
  {}, 
  bucketName: "bucket-name",
);
  • delete
final Response<dynamic> resp = await Client().deleteBucketPolicy(
  bucketName: "bucket-name",
);

Drop a ⭐ if it is help to you