From a45f5cc1ce5a8e7fbb2237db81c48cf2a9c3b613 Mon Sep 17 00:00:00 2001 From: dyh Date: Sun, 14 Jan 2024 22:35:44 +0800 Subject: [PATCH 1/2] [dyh] -feat: add MultipartUpload method --- lib/src/client.dart | 75 ++++++++++++++++++++++++++++++++++++++ lib/src/client_api.dart | 23 ++++++++++++ lib/src/model/auth.dart | 20 ++++++++-- lib/src/model/request.dart | 4 ++ 4 files changed, 118 insertions(+), 4 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index 7e51787..7f363ee 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -714,4 +714,79 @@ class Client with AuthMixin, HttpMixin implements ClientApi { return await Future.wait(deletes); } + + /// initiateMultipartUpload from oss + @override + Future> initiateMultipartUpload( + String fileKey, { + String? bucketName, + CancelToken? cancelToken, + }) async { + final String bucket = bucketName ?? this.bucketName; + final Auth auth = await getAuth(); + + final String url = "https://$bucket.$endpoint/$fileKey?uploads"; + final HttpRequest request = HttpRequest.post(url); + auth.sign(request, bucket, fileKey); + + return _dio.post( + request.url, + cancelToken: cancelToken, + options: Options(headers: request.headers), + ); + } + + /// uploadPart from oss + @override + Future> uploadPart( + String fileKey, + List partData, + int partNumber, + String uploadId, { + String? bucketName, + CancelToken? cancelToken, + }) async { + final String bucket = bucketName ?? this.bucketName; + final Auth auth = await getAuth(); + + final String url = + "https://$bucket.$endpoint/$fileKey?partNumber=$partNumber&uploadId=$uploadId"; + final HttpRequest request = HttpRequest.put(url, headers: { + 'content-type': 'application/octet-stream', + }); + auth.sign(request, bucket, fileKey); + + return _dio.put( + request.url, + data: partData, + cancelToken: cancelToken, + options: Options(headers: request.headers), + ); + } + + /// completeMultipartUpload from oss + @override + Future> completeMultipartUpload( + String fileKey, + String uploadId, + String data, { + String? bucketName, + CancelToken? cancelToken, + }) async { + final String bucket = bucketName ?? this.bucketName; + final Auth auth = await getAuth(); + + final String url = "https://$bucket.$endpoint/$fileKey?uploadId=$uploadId"; + final HttpRequest request = HttpRequest.post(url, headers: { + 'content-type': 'application/xml', + }); + auth.sign(request, bucket, fileKey); + + return _dio.post( + request.url, + data: data, + cancelToken: cancelToken, + options: Options(headers: request.headers), + ); + } } diff --git a/lib/src/client_api.dart b/lib/src/client_api.dart index 9cc2c95..dba3faa 100644 --- a/lib/src/client_api.dart +++ b/lib/src/client_api.dart @@ -156,4 +156,27 @@ abstract class ClientApi { String? bucketName, CancelToken? cancelToken, }); + + Future> initiateMultipartUpload( + String fileKey, { + String? bucketName, + CancelToken? cancelToken, + }); + + Future> uploadPart( + String fileKey, + List partData, + int partNumber, + String uploadId, { + String? bucketName, + CancelToken? cancelToken, + }); + + Future> completeMultipartUpload( + String fileKey, + String uploadId, + String data, { + String? bucketName, + CancelToken? cancelToken, + }); } diff --git a/lib/src/model/auth.dart b/lib/src/model/auth.dart index 4537103..414466e 100644 --- a/lib/src/model/auth.dart +++ b/lib/src/model/auth.dart @@ -76,7 +76,8 @@ class Auth { final String contentType = req.headers['content-type'] ?? ''; final String date = req.headers['x-oss-date'] ?? ''; final String headerString = _getHeaderString(req); - final String resourceString = _getResourceString(bucket, key, req.param); + final String resourceString = + _getResourceString(bucket, key, req.param, req.oriUrl); final String stringToSign = [ req.method, contentMd5, @@ -104,17 +105,28 @@ class Auth { String _getResourceString( String bucket, String fileKey, - Map param, - ) { + Map param, [ + String? url, + ]) { String path = "/"; if (bucket.isNotEmpty) path += "$bucket/"; if (fileKey.isNotEmpty) path += fileKey; + + bool hasSuffix = false; + + if (url != null) { + if (url.lastIndexOf("?") != -1) { + hasSuffix = true; + path += "?${url.split("?").last}"; + } + } + final String signedParamString = param.keys .where((key) => SignParameters.signedParams.contains(key)) .map((item) => "$item=${param[item]}") .join("&"); if (signedParamString.isNotEmpty) { - path += "?$signedParamString"; + path += "${hasSuffix ? '' : '?'}$signedParamString"; } return path; diff --git a/lib/src/model/request.dart b/lib/src/model/request.dart index cc8ca7e..34c2244 100644 --- a/lib/src/model/request.dart +++ b/lib/src/model/request.dart @@ -17,6 +17,10 @@ class HttpRequest { return queryString.isEmpty ? _url : "$_url?$queryString"; } + String get oriUrl { + return _url; + } + factory HttpRequest.get( String url, { Map? parameters, From 1b7a37e5648e18054d1df03f6332603a5bdbae87 Mon Sep 17 00:00:00 2001 From: dyh Date: Sat, 13 Apr 2024 14:58:00 +0800 Subject: [PATCH 2/2] [dyh] -feat: add MultipartUpload method --- lib/src/client.dart | 6 +++--- lib/src/model/auth.dart | 20 ++++---------------- lib/src/model/request.dart | 4 ---- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index 7f363ee..a7c86b2 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -727,7 +727,7 @@ class Client with AuthMixin, HttpMixin implements ClientApi { final String url = "https://$bucket.$endpoint/$fileKey?uploads"; final HttpRequest request = HttpRequest.post(url); - auth.sign(request, bucket, fileKey); + auth.sign(request, bucket, "$fileKey?uploads"); return _dio.post( request.url, @@ -754,7 +754,7 @@ class Client with AuthMixin, HttpMixin implements ClientApi { final HttpRequest request = HttpRequest.put(url, headers: { 'content-type': 'application/octet-stream', }); - auth.sign(request, bucket, fileKey); + auth.sign(request, bucket, "$fileKey?partNumber=$partNumber&uploadId=$uploadId"); return _dio.put( request.url, @@ -780,7 +780,7 @@ class Client with AuthMixin, HttpMixin implements ClientApi { final HttpRequest request = HttpRequest.post(url, headers: { 'content-type': 'application/xml', }); - auth.sign(request, bucket, fileKey); + auth.sign(request, bucket, "$fileKey?uploadId=$uploadId"); return _dio.post( request.url, diff --git a/lib/src/model/auth.dart b/lib/src/model/auth.dart index 414466e..4537103 100644 --- a/lib/src/model/auth.dart +++ b/lib/src/model/auth.dart @@ -76,8 +76,7 @@ class Auth { final String contentType = req.headers['content-type'] ?? ''; final String date = req.headers['x-oss-date'] ?? ''; final String headerString = _getHeaderString(req); - final String resourceString = - _getResourceString(bucket, key, req.param, req.oriUrl); + final String resourceString = _getResourceString(bucket, key, req.param); final String stringToSign = [ req.method, contentMd5, @@ -105,28 +104,17 @@ class Auth { String _getResourceString( String bucket, String fileKey, - Map param, [ - String? url, - ]) { + Map param, + ) { String path = "/"; if (bucket.isNotEmpty) path += "$bucket/"; if (fileKey.isNotEmpty) path += fileKey; - - bool hasSuffix = false; - - if (url != null) { - if (url.lastIndexOf("?") != -1) { - hasSuffix = true; - path += "?${url.split("?").last}"; - } - } - final String signedParamString = param.keys .where((key) => SignParameters.signedParams.contains(key)) .map((item) => "$item=${param[item]}") .join("&"); if (signedParamString.isNotEmpty) { - path += "${hasSuffix ? '' : '?'}$signedParamString"; + path += "?$signedParamString"; } return path; diff --git a/lib/src/model/request.dart b/lib/src/model/request.dart index 34c2244..cc8ca7e 100644 --- a/lib/src/model/request.dart +++ b/lib/src/model/request.dart @@ -17,10 +17,6 @@ class HttpRequest { return queryString.isEmpty ? _url : "$_url?$queryString"; } - String get oriUrl { - return _url; - } - factory HttpRequest.get( String url, { Map? parameters,