-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathCosXmlReactNative.m
276 lines (233 loc) · 10.9 KB
/
CosXmlReactNative.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#import "CosXmlReactNative.h"
#import <QCloudCore/QCloudCore.h>
#import <QCloudcore/NSObject+QCloudModel.h>
#import <QCloudCOSXML/QCloudCOSXMLTransfer.h>
#import <QCloudCOSXML/QCloudCOSXMLDownloadObjectRequest.h>
#import <React/RCTConvert.h>
@interface CosXmlReactNative() <QCloudSignatureProvider, QCloudCredentailFenceQueueDelegate>
@property (nonatomic, strong) QCloudCredentailFenceQueue* credentialFenceQueue;
@end
NSString * const PROGRESS_EVENT = @"COSTransferProgressUpdate";
NSString * const UPDATE_CREDENTIAL_EVENT = @"COSUpdateSessionCredential";
@implementation CosXmlReactNative {
dispatch_group_t g;
QCloudCredential* sessionCredential;
NSMutableDictionary<NSString*, QCloudCOSXMLUploadObjectRequest*> * requests;
NSMutableDictionary<NSString*, NSData*> * resumeDataList;
NSString* secretId;
NSString* secretKey;
BOOL hasObversers;
}
RCT_EXPORT_MODULE()
- (NSArray<NSString *> *)supportedEvents {
return @[PROGRESS_EVENT, UPDATE_CREDENTIAL_EVENT];
}
/**
用固定密钥初始化
*/
RCT_REMAP_METHOD(initWithPlainSecret, initWithConfig: (NSDictionary *)config plainSecret:(NSDictionary*)credential) {
[self initService:config];
secretId = [credential objectForKey:@"secretId"];
secretKey = [credential objectForKey:@"secretKey"];
}
/**
用临时密钥回调初始化
*/
RCT_REMAP_METHOD(initWithSessionCredentialCallback, initWithConfig:(NSDictionary*)config) {
[self initService:config];
}
/**
更新临时密钥
*/
RCT_EXPORT_METHOD(updateSessionCredential:(NSDictionary *)credentialInfo) {
if (!sessionCredential) {
sessionCredential = [QCloudCredential new];
}
sessionCredential.secretID = credentialInfo[@"tmpSecretId"];
sessionCredential.secretKey = credentialInfo[@"tmpSecretKey"];
sessionCredential.experationDate = [NSDate dateWithTimeIntervalSince1970:[RCTConvert int:credentialInfo[@"expiredTime"]]];
sessionCredential.token = credentialInfo[@"sessionToken"];
if (g) {
dispatch_group_leave(g);
}
}
RCT_EXPORT_METHOD(putObject:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
NSString *requestId = [options objectForKey:@"requestId"];
NSData *resumeData = [resumeDataList objectForKey:requestId];
QCloudCOSXMLUploadObjectRequest* put;
if (resumeData) {
put = [QCloudCOSXMLUploadObjectRequest requestWithRequestData:resumeData];
// remove resume data from cache
[resumeDataList removeObjectForKey:requestId];
} else {
put = [QCloudCOSXMLUploadObjectRequest new];
NSString* srcPath = [options objectForKey:@"fileUri"];
if ([srcPath hasPrefix:@"file://"] || [srcPath hasPrefix:@"File://"]) {
srcPath = [srcPath substringFromIndex:7];
}
put.object = [options objectForKey:@"object"];
put.bucket = [options objectForKey:@"bucket"];
put.body = [NSURL fileURLWithPath:srcPath];
}
[put setSendProcessBlock:^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
NSLog(@"upload : totalSend %lld aim %lld", totalBytesSent, totalBytesExpectedToSend);
if (self->hasObversers && requestId) {
NSDictionary* info = @{@"requestId": requestId,
@"processedBytes": @(totalBytesSent),
@"targetBytes": @(totalBytesExpectedToSend)
};
dispatch_async(dispatch_get_main_queue(), ^{
[self sendMessageToRN:info toChannel:PROGRESS_EVENT];
});
}
}];
[put setInitMultipleUploadFinishBlock:^(QCloudInitiateMultipartUploadResult * _Nullable multipleUploadInitResult, QCloudCOSXMLUploadObjectResumeData _Nullable resumeData) {
}];
[put setFinishBlock:^(id outputObject, NSError* error) {
// remove rquest from cache
[self->requests removeObjectForKey:requestId];
if (error) {
reject([@(error.code) stringValue], error.localizedDescription, error);
} else {
NSMutableDictionary* dic = [NSMutableDictionary new];
QCloudUploadObjectResult* result = (QCloudUploadObjectResult *) outputObject;
[dic setObject:result.bucket forKey:@"Bucket"];
[dic setObject:result.key forKey:@"Key"];
[dic setObject:result.eTag forKey:@"ETag"];
[dic setObject:result.location forKey:@"Location"];
if (result.versionID) {
[dic setObject:result.versionID forKey:@"VersionID"];
}
resolve([dic copy]);
}
}];
// add request to cache
[requests setObject:put forKey:requestId];
[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
}
RCT_EXPORT_METHOD(pauseUpload:(NSString *)requestId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
QCloudCOSXMLUploadObjectRequest* request = [requests objectForKey:requestId];
if (request) {
NSError *error;
NSData* resumeData = [request cancelByProductingResumeData:&error];
if (error) {
reject([@(error.code) stringValue], error.localizedDescription, error);
} else {
// remove rquest from cache
[requests removeObjectForKey:requestId];
// add resume data to cache
[resumeDataList setObject:resumeData forKey:requestId];
resolve(@"");
}
} else {
NSLog(@"No Request Found for %@", requestId);
}
}
RCT_EXPORT_METHOD(getObject:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
QCloudCOSXMLDownloadObjectRequest* request = [QCloudCOSXMLDownloadObjectRequest new];
request.bucket = [options objectForKey:@"bucket"];
request.object = [options objectForKey:@"object"];
NSString* filePath = [options objectForKey:@"filePath"];
if (!filePath) {
NSString* dir = [NSTemporaryDirectory() stringByAppendingPathComponent:@"cos_download"];
QCloudEnsurePathExist(dir);
filePath = QCloudPathJoin(dir, request.object);
}
request.downloadingURL = [NSURL fileURLWithPath:filePath];
[request setFinishBlock:^(id outputObject, NSError *error) {
if (error) {
reject([@(error.code) stringValue], error.localizedDescription, error);
} else {
resolve(filePath);
}
}];
[request setDownProcessBlock:^(int64_t bytesDownload, int64_t totalBytesDownload, int64_t totalBytesExpectedToDownload) {
NSLog(@"download : totalSend %lld aim %lld", totalBytesDownload, totalBytesExpectedToDownload);
NSString *requestId = [options objectForKey:@"requestId"];
if (self->hasObversers && requestId) {
NSDictionary* info = @{@"requestId": requestId,
@"processedBytes": @(totalBytesDownload),
@"targetBytes": @(totalBytesExpectedToDownload)
};
dispatch_async(dispatch_get_main_queue(), ^{
[self sendMessageToRN:info toChannel:PROGRESS_EVENT];
});
}
}];
[[QCloudCOSTransferMangerService defaultCOSTransferManager] DownloadObject:request];
}
RCT_EXPORT_METHOD(headObject:(NSDictionary*) options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
QCloudHeadObjectRequest* headRequest = [QCloudHeadObjectRequest new];
headRequest.bucket = [options objectForKey:@"bucket"];
headRequest.object = [options objectForKey:@"object"];
[headRequest setFinishBlock:^(NSDictionary* result, NSError* error) {
if (error) {
reject([@(error.code) stringValue], error.localizedDescription, error);
} else {
resolve(result);
}
}];
[[QCloudCOSXMLService defaultCOSXML] HeadObject:headRequest];
}
- (void)startObserving {
hasObversers = YES;
}
- (void)stopObserving {
hasObversers = NO;
}
- (void) initService:(NSDictionary*)config {
QCloudServiceConfiguration* configuration = [[QCloudServiceConfiguration alloc] init];
configuration.signatureProvider = self;
QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] init];
endpoint.regionName = [RCTConvert NSString:[config objectForKey:@"region"]];
endpoint.useHTTPS = YES;
configuration.endpoint = endpoint;
[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];
[QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration:configuration];
self.credentialFenceQueue = [QCloudCredentailFenceQueue new];
self.credentialFenceQueue.delegate = self;
requests = [NSMutableDictionary new];
resumeDataList = [NSMutableDictionary new];
}
-(void)sendMessageToRN:(NSDictionary*)info toChannel:(NSString*)channel {
[self sendEventWithName:channel body:[info copy]];
}
- (void)fenceQueue:(QCloudCredentailFenceQueue *)queue requestCreatorWithContinue:(QCloudCredentailFenceQueueContinue)continueBlock {
[self sendMessageToRN:[NSDictionary new] toChannel:UPDATE_CREDENTIAL_EVENT];
g = dispatch_group_create();
dispatch_group_enter(g);
dispatch_group_notify(g, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (self->sessionCredential && [self->sessionCredential.experationDate compare:NSDate.date] == NSOrderedDescending) {
QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc] initWithCredential:self->sessionCredential];
continueBlock(creator, nil);
} else {
continueBlock(nil, [NSError errorWithDomain:NSURLErrorDomain code:-1111 userInfo:@{NSLocalizedDescriptionKey:@"没有获取到临时密钥"}]);
}
self->g = nil;
});
}
- (void) signatureWithFields:(QCloudSignatureFields*)fileds
request:(QCloudBizHTTPRequest*)request
urlRequest:(NSMutableURLRequest*)urlRequst
compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock {
if (secretKey && secretId) {
// 使用永久秘钥
QCloudCredential* credential = [QCloudCredential new];
credential.secretID = secretId;
credential.secretKey = secretKey;
QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc] initWithCredential:credential];
QCloudSignature* signature = [creator signatureForData:urlRequst];
continueBlock(signature, nil);
} else {
// 调用回调获取秘钥
[self.credentialFenceQueue performAction:^(QCloudAuthentationCreator *creator, NSError *error) {
if (error) {
continueBlock(nil, error);
} else {
QCloudSignature* signature = [creator signatureForData:urlRequst];
continueBlock(signature, nil);
}
}];
}
}
@end