diff --git a/README.md b/README.md index a840e96..43308e9 100644 --- a/README.md +++ b/README.md @@ -242,9 +242,16 @@ AliyunOSS.initWithServerSTS(/*local auth server*/, endPoint, configuration); ### asyncUpload +```javascript +const option = { + // optional + callbackParam:{}, + // optional + callbackVars:{}, +} +AliyunOSS.asyncUpload(bucketname, objectKey, filepath, option).then().catch() ``` -AliyunOSS.asyncUpload(bucketname, objectKey, filepath).then().catch() -``` +callbackParam与callbackVars参数格式请参考[阿里云文档](https://help.aliyun.com/document_detail/31989.html?spm=a2c4g.11186623.6.703.395472c1fxLRVz) ### asyncAppendObject ### asyncResumableUpload ### initMultipartUpload diff --git a/android/build.gradle b/android/build.gradle index 261655d..6f0f9f5 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,22 +2,23 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.1' + classpath 'com.android.tools.build:gradle:3.4.0' } } apply plugin: 'com.android.library' android { - compileSdkVersion 23 - buildToolsVersion '27.0.3' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 16 - targetSdkVersion 22 + targetSdkVersion 28 versionCode 1 versionName "1.0" } @@ -28,10 +29,11 @@ android { repositories { mavenCentral() + google() } dependencies { - compile 'com.facebook.react:react-native:+' - compile 'com.aliyun.dpa:oss-android-sdk:+' + implementation 'com.facebook.react:react-native:+' + implementation 'com.aliyun.dpa:oss-android-sdk:+' } \ No newline at end of file diff --git a/android/src/main/java/com/reactlibrary/AliyunUploadManager.java b/android/src/main/java/com/reactlibrary/AliyunUploadManager.java index 2d08bfa..d8d47b2 100644 --- a/android/src/main/java/com/reactlibrary/AliyunUploadManager.java +++ b/android/src/main/java/com/reactlibrary/AliyunUploadManager.java @@ -39,6 +39,7 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.reactlibrary.utils.FileUtils; +import com.reactlibrary.utils.RNUtils; import java.io.File; import java.io.FileInputStream; @@ -55,7 +56,6 @@ public class AliyunUploadManager { /** * AliyunUploadManager contructor - * @param oss */ public AliyunUploadManager(OSS oss) { mOSS = oss; @@ -63,14 +63,9 @@ public AliyunUploadManager(OSS oss) { /** * asyncUpload - * @param context - * @param bucketName - * @param ossFile - * @param sourceFile - * @param options - * @param promise */ - public void asyncUpload(final ReactContext context, String bucketName, String ossFile, String sourceFile, ReadableMap options, final Promise promise) { + public void asyncUpload(final ReactContext context, String bucketName, String ossFile, String sourceFile, + ReadableMap options, final Promise promise) { // Content to file:// start Uri selectedVideoUri = Uri.parse(sourceFile); @@ -80,10 +75,13 @@ public void asyncUpload(final ReactContext context, String bucketName, String os try { String[] proj = {MediaStore.Images.Media.DATA}; cursor = context.getCurrentActivity().getContentResolver().query(selectedVideoUri, proj, null, null, null); - if (cursor == null) sourceFile = selectedVideoUri.getPath(); - int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - sourceFile = cursor.getString(column_index); + if (cursor == null) { + sourceFile = selectedVideoUri.getPath(); + } else { + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + sourceFile = cursor.getString(column_index); + } } catch (Exception e) { sourceFile = FileUtils.getFilePathFromURI(context.getCurrentActivity(), selectedVideoUri); } finally { @@ -97,21 +95,37 @@ public void asyncUpload(final ReactContext context, String bucketName, String os metadata.setContentType("application/octet-stream"); put.setMetadata(metadata); + final int progressStep = options.hasKey("progressStep") ? options.getInt("progressStep") : 0; + // set callback put.setProgressCallback(new OSSProgressCallback() { + double lastPercent = 0; + @Override public void onProgress(PutObjectRequest request, long currentSize, long totalSize) { Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize); - String str_currentSize = Long.toString(currentSize); - String str_totalSize = Long.toString(totalSize); - WritableMap onProgressValueData = Arguments.createMap(); - onProgressValueData.putString("currentSize", str_currentSize); - onProgressValueData.putString("totalSize", str_totalSize); - context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit("uploadProgress", onProgressValueData); + double percent = currentSize * 100.0 / totalSize; + if (percent - lastPercent >= progressStep) { + String str_currentSize = Long.toString(currentSize); + String str_totalSize = Long.toString(totalSize); + WritableMap onProgressValueData = Arguments.createMap(); + onProgressValueData.putString("currentSize", str_currentSize); + onProgressValueData.putString("totalSize", str_totalSize); + context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit("uploadProgress", onProgressValueData); + lastPercent = percent; + } } }); + if (options.hasKey("callbackParam")) { + put.setCallbackParam(RNUtils.convertMap(options.getMap("callbackParam"))); + } + + if (options.hasKey("callbackVars")) { + put.setCallbackVars(RNUtils.convertMap(options.getMap("callbackVars"))); + } + OSSAsyncTask task = mOSS.asyncPutObject(put, new OSSCompletedCallback() { @Override public void onSuccess(PutObjectRequest request, PutObjectResult result) { @@ -122,8 +136,9 @@ public void onSuccess(PutObjectRequest request, PutObjectResult result) { } @Override - public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) { - PromiseExceptionManager.resolvePromiseException(clientExcepion,serviceException,promise); + public void onFailure(PutObjectRequest request, ClientException clientExcepion, + ServiceException serviceException) { + PromiseExceptionManager.resolvePromiseException(clientExcepion, serviceException, promise); } }); Log.d("AliyunOSS", "OSS uploadObjectAsync ok!"); @@ -131,13 +146,9 @@ public void onFailure(PutObjectRequest request, ClientException clientExcepion, /** * asyncAppendObject - * @param bucketName - * @param objectKey - * @param uploadFilePath - * @param options - * @param promise */ - public void asyncAppendObject(final ReactContext context,String bucketName,String objectKey,String uploadFilePath,ReadableMap options,final Promise promise) { + public void asyncAppendObject(final ReactContext context, String bucketName, String objectKey, + String uploadFilePath, ReadableMap options, final Promise promise) { // Content to file:// start Uri selectedVideoUri = Uri.parse(uploadFilePath); @@ -184,33 +195,31 @@ public void onProgress(AppendObjectRequest request, long currentSize, long total } }); - OSSAsyncTask task = mOSS.asyncAppendObject(append, new OSSCompletedCallback() { - @Override - public void onSuccess(AppendObjectRequest request, AppendObjectResult result) { - Log.d("AppendObject", "AppendSuccess"); - Log.d("NextPosition", "" + result.getNextPosition()); - WritableMap map = Arguments.createMap(); - map.putString("AppendObject","AppendSuccess"); - map.putDouble("NextPosition", result.getNextPosition()); - promise.resolve(map); - } - @Override - public void onFailure(AppendObjectRequest request, ClientException clientExcepion, ServiceException serviceException) { - PromiseExceptionManager.resolvePromiseException(clientExcepion,serviceException,promise); - } - }); + OSSAsyncTask task = mOSS + .asyncAppendObject(append, new OSSCompletedCallback() { + @Override + public void onSuccess(AppendObjectRequest request, AppendObjectResult result) { + Log.d("AppendObject", "AppendSuccess"); + Log.d("NextPosition", "" + result.getNextPosition()); + WritableMap map = Arguments.createMap(); + map.putString("AppendObject", "AppendSuccess"); + map.putDouble("NextPosition", result.getNextPosition()); + promise.resolve(map); + } + + @Override + public void onFailure(AppendObjectRequest request, ClientException clientExcepion, + ServiceException serviceException) { + PromiseExceptionManager.resolvePromiseException(clientExcepion, serviceException, promise); + } + }); } /** * asyncResumableUpload - * - * @param bucketName - * @param objectKey - * @param uploadFilePath - * @param options - * @param promise */ - public void asyncResumableUpload(final ReactContext context, String bucketName, String objectKey, String uploadFilePath, ReadableMap options, final Promise promise) { + public void asyncResumableUpload(final ReactContext context, String bucketName, String objectKey, + String uploadFilePath, ReadableMap options, final Promise promise) { ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectKey, uploadFilePath); @@ -229,26 +238,26 @@ public void onProgress(ResumableUploadRequest request, long currentSize, long to } }); - OSSAsyncTask resumableTask = mOSS.asyncResumableUpload(request, new OSSCompletedCallback() { - @Override - public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) { - promise.resolve("resumableUpload success"); - } - - @Override - public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) { - PromiseExceptionManager.resolvePromiseException(clientExcepion, serviceException, promise); - } - }); + OSSAsyncTask resumableTask = mOSS + .asyncResumableUpload(request, new OSSCompletedCallback() { + @Override + public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) { + promise.resolve("resumableUpload success"); + } + + @Override + public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, + ServiceException serviceException) { + PromiseExceptionManager.resolvePromiseException(clientExcepion, serviceException, promise); + } + }); } /** * initMultipartUpload - * @param bucketName - * @param objectKey - * @param promise */ - public void initMultipartUpload(String bucketName,String objectKey,final Promise promise) { + public void initMultipartUpload(String bucketName, String objectKey, final Promise promise) { String uploadId; InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest(bucketName, objectKey); InitiateMultipartUploadResult initResult = null; @@ -267,15 +276,9 @@ public void initMultipartUpload(String bucketName,String objectKey,final Promise /** * multipartUpload - * @param context - * @param bucketName - * @param objectKey - * @param uploadId - * @param filepath - * @param options - * @param promise */ - public void multipartUpload(final ReactContext context,String bucketName, String objectKey, String uploadId,String filepath, ReadableMap options,final Promise promise) { + public void multipartUpload(final ReactContext context, String bucketName, String objectKey, String uploadId, + String filepath, ReadableMap options, final Promise promise) { Uri selectedVideoUri = Uri.parse(filepath); // 1. content uri -> file path @@ -309,7 +312,7 @@ public void multipartUpload(final ReactContext context,String bucketName, String long uploadedLength = 0; List partETags = new ArrayList(); // 保存分片上传的结果 while (uploadedLength < fileLength) { - int partLength = (int)Math.min(partSize, fileLength - uploadedLength); + int partLength = (int) Math.min(partSize, fileLength - uploadedLength); byte[] partData = new byte[0]; // 按照分片大小读取文件的一段内容 try { partData = IOUtils.readStreamAsBytesArray(input, partLength); @@ -334,7 +337,8 @@ public void multipartUpload(final ReactContext context,String bucketName, String currentIndex++; } - CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(bucketName, objectKey,uploadId,partETags); + CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, + partETags); CompleteMultipartUploadResult completeResult = null; try { completeResult = mOSS.completeMultipartUpload(complete); @@ -354,12 +358,8 @@ public void multipartUpload(final ReactContext context,String bucketName, String /** * abortMultipartUpload - * @param bucketName - * @param objectKey - * @param uploadId - * @param promise */ - public void abortMultipartUpload(String bucketName,String objectKey,String uploadId,final Promise promise) { + public void abortMultipartUpload(String bucketName, String objectKey, String uploadId, final Promise promise) { AbortMultipartUploadRequest abort = new AbortMultipartUploadRequest(bucketName, objectKey, uploadId); try { mOSS.abortMultipartUpload(abort); @@ -375,12 +375,8 @@ public void abortMultipartUpload(String bucketName,String objectKey,String uploa /** * listParts - * @param bucketName - * @param objectKey - * @param uploadId - * @param promise */ - public void listParts (String bucketName,String objectKey,String uploadId,final Promise promise) { + public void listParts(String bucketName, String objectKey, String uploadId, final Promise promise) { ListPartsRequest listParts = new ListPartsRequest(bucketName, objectKey, uploadId); ListPartsResult result = null; try { @@ -401,9 +397,9 @@ public void listParts (String bucketName,String objectKey,String uploadId,final Log.d("listParts", "lastModified: " + result.getParts().get(i).getLastModified()); Log.d("listParts", "partSize: " + result.getParts().get(i).getSize()); listPartsData.putInt("partNum" + i, result.getParts().get(i).getPartNumber()); - listPartsData.putString("partEtag"+i,result.getParts().get(i).getETag()); + listPartsData.putString("partEtag" + i, result.getParts().get(i).getETag()); // listPartsData.("lastModified" + i,result.getParts().get(i).getLastModified()); - listPartsData.putDouble("partSize"+i,result.getParts().get(i).getSize()); + listPartsData.putDouble("partSize" + i, result.getParts().get(i).getSize()); } promise.resolve(listPartsData); } diff --git a/android/src/main/java/com/reactlibrary/utils/RNUtils.java b/android/src/main/java/com/reactlibrary/utils/RNUtils.java new file mode 100644 index 0000000..32d7fda --- /dev/null +++ b/android/src/main/java/com/reactlibrary/utils/RNUtils.java @@ -0,0 +1,30 @@ +package com.reactlibrary.utils; + +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableMapKeySetIterator; +import com.facebook.react.bridge.ReadableType; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by kevin.bai on 2019-04-28. + */ +public class RNUtils { + /** + * 将ReadableMap对象转为Map对象,只支持String类型的value + * @param param + * @return + */ + public static Map convertMap(ReadableMap param){ + Map result = new HashMap<>(); + ReadableMapKeySetIterator iterator = param.keySetIterator(); + while(iterator.hasNextKey()){ + String key = iterator.nextKey(); + if (param.getType(key) == ReadableType.String){ + result.put(key, param.getString(key)); + } + } + return result; + } +} diff --git a/ios/RNAliyunOSS+AUTH.m b/ios/RNAliyunOSS+AUTH.m index 1bfcc6d..cc43984 100644 --- a/ios/RNAliyunOSS+AUTH.m +++ b/ios/RNAliyunOSS+AUTH.m @@ -65,14 +65,14 @@ @implementation RNAliyunOSS (AUTH) /** initWithServerSTS */ -RCT_EXPORT_METHOD(initWithServerSTS:(NSString *)server endPoint:(NSString *)endPoint configuration:(NSDictionary *)configuration){ - //直接访问鉴权服务器(推荐,token过期后可以自动更新) - id credential = [[OSSAuthCredentialProvider alloc] initWithAuthServerUrl:server]; +// RCT_EXPORT_METHOD(initWithServerSTS:(NSString *)server endPoint:(NSString *)endPoint configuration:(NSDictionary *)configuration){ +// //直接访问鉴权服务器(推荐,token过期后可以自动更新) +// id credential = [[OSSAuthCredentialProvider alloc] initWithAuthServerUrl:server]; - [self initConfiguration: configuration]; +// [self initConfiguration: configuration]; - self.client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential clientConfiguration:self.clientConfiguration]; -} +// self.client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential clientConfiguration:self.clientConfiguration]; +// } @end diff --git a/ios/RNAliyunOSS+UPLOAD.m b/ios/RNAliyunOSS+UPLOAD.m index d9373be..9b4ba52 100644 --- a/ios/RNAliyunOSS+UPLOAD.m +++ b/ios/RNAliyunOSS+UPLOAD.m @@ -19,6 +19,26 @@ @implementation RNAliyunOSS (UPLOAD) put.objectKey = objectKey; put.uploadingData = data; + if([[options allKeys] containsObject:@"callbackVars"]) { + if ([options[@"callbackVars"] isKindOfClass: [NSDictionary class]]) { + put.callbackVar = options[@"callbackVars"]; + } else { + NSLog(@"callbackVars 类型需要为字典类型"); + } + } else { + NSLog(@"options未包含 callbackVars 字段"); + } + + if([[options allKeys] containsObject:@"callbackParam"]) { + if ([options[@"callbackParam"] isKindOfClass: [NSDictionary class]]) { + put.callbackParam = options[@"callbackParam"]; + } else { + NSLog(@"callbackParam 类型需要为字典类型"); + } + } else { + NSLog(@"options未包含 callbackParam 字段"); + } + // 设置Content-Type,可选 // put.contentType = @"application/octet-stream"; // // 设置MD5校验,可选