Skip to content

Commit

Permalink
Merge pull request #62 from Vydia/ios-asset-library-upload
Browse files Browse the repository at this point in the history
Support iOS assets-library url
  • Loading branch information
StevePotter committed Feb 8, 2018
2 parents 6fbc204 + 709228c commit 4513d2b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 10 deletions.
61 changes: 52 additions & 9 deletions ios/VydiaRNFileUploader.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import <MobileCoreServices/MobileCoreServices.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTBridgeModule.h>
#import <Photos/Photos.h>

@interface VydiaRNFileUploader : RCTEventEmitter <RCTBridgeModule, NSURLSessionTaskDelegate>
{
Expand Down Expand Up @@ -56,15 +57,13 @@ - (void)_sendEventWithName:(NSString *)eventName body:(id)body {
@try {
NSURL *fileUri = [NSURL URLWithString: path];
NSString *pathWithoutProtocol = [fileUri path];

NSString *name = [fileUri lastPathComponent];
NSString *extension = [name pathExtension];
bool exists = [[NSFileManager defaultManager] fileExistsAtPath:pathWithoutProtocol];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys: name, @"name", nil];

[params setObject:extension forKey:@"extension"];
[params setObject:[NSNumber numberWithBool:exists] forKey:@"exists"];

if (exists)
{
[params setObject:[self guessMIMETypeFromFileName:name] forKey:@"mimeType"];
Expand All @@ -76,7 +75,6 @@ - (void)_sendEventWithName:(NSString *)eventName body:(id)body {
[params setObject:[NSNumber numberWithLong:fileSize] forKey:@"size"];
}
}

resolve(params);
}
@catch (NSException *exception) {
Expand All @@ -97,6 +95,36 @@ - (NSString *)guessMIMETypeFromFileName: (NSString *)fileName {
return (__bridge NSString *)(MIMEType);
}

/*
Utility method to copy a PHAsset file into a local temp file, which can then be uploaded.
*/
- (void)copyAssetToFile: (NSString *)assetUrl completionHandler: (void(^)(NSString *__nullable tempFileUrl, NSError *__nullable error))completionHandler {
NSURL *url = [NSURL URLWithString:assetUrl];
PHAsset *asset = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil].lastObject;
if (!asset) {
NSMutableDictionary* details = [NSMutableDictionary dictionary];
[details setValue:@"Asset could not be fetched. Are you missing permissions?" forKey:NSLocalizedDescriptionKey];
completionHandler(nil, [NSError errorWithDomain:@"RNUploader" code:5 userInfo:details]);
return;
}
PHAssetResource *assetResource = [[PHAssetResource assetResourcesForAsset:asset] firstObject];
NSString *pathToWrite = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
NSURL *pathUrl = [NSURL fileURLWithPath:pathToWrite];
NSString *fileURI = pathUrl.absoluteString;

PHAssetResourceRequestOptions *options = [PHAssetResourceRequestOptions new];
options.networkAccessAllowed = YES;

[[PHAssetResourceManager defaultManager] writeDataForAssetResource:assetResource toFile:pathUrl options:options completionHandler:^(NSError * _Nullable e) {
if (e == nil) {
completionHandler(fileURI, nil);
}
else {
completionHandler(nil, e);
}
}];
}

/*
* Starts a file upload.
* Options are passed in as the first argument as a js hash:
Expand All @@ -117,7 +145,7 @@ - (NSString *)guessMIMETypeFromFileName: (NSString *)fileName {
}

NSString *uploadUrl = options[@"url"];
NSString *fileURI = options[@"path"];
__block NSString *fileURI = options[@"path"];
NSString *method = options[@"method"] ?: @"POST";
NSString *uploadType = options[@"type"] ?: @"raw";
NSString *fieldName = options[@"field"];
Expand All @@ -137,6 +165,23 @@ - (NSString *)guessMIMETypeFromFileName: (NSString *)fileName {
}
}];


// asset library files have to be copied over to a temp file. they can't be uploaded directly
if ([fileURI hasPrefix:@"assets-library"]) {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[self copyAssetToFile:fileURI completionHandler:^(NSString * _Nullable tempFileUrl, NSError * _Nullable error) {
if (error) {
dispatch_group_leave(group);
reject(@"RN Uploader", @"Asset could not be copied to temp file.", nil);
return;
}
fileURI = tempFileUrl;
dispatch_group_leave(group);
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

NSURLSessionDataTask *uploadTask;

if ([uploadType isEqualToString:@"multipart"]) {
Expand Down Expand Up @@ -189,7 +234,6 @@ - (NSData *)createBodyWithBoundary:(NSString *)boundary
NSString *pathWithoutProtocol = [fileUri path];

NSData *data = [[NSFileManager defaultManager] contentsAtPath:pathWithoutProtocol];

NSString *filename = [path lastPathComponent];
NSString *mimetype = [self guessMIMETypeFromFileName:path];

Expand All @@ -208,7 +252,7 @@ - (NSURLSession *)urlSession {
if (_urlSession == nil) {
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:BACKGROUND_SESSION_ID];
_urlSession = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
}
}
return _urlSession;
}

Expand All @@ -223,7 +267,7 @@ - (void)URLSession:(NSURLSession *)session
if (response != nil)
{
[data setObject:[NSNumber numberWithInteger:response.statusCode] forKey:@"responseCode"];
}
}
//Add data that was collected earlier by the didReceiveData method
NSMutableData *responseData = _responsesData[@(task.taskIdentifier)];
if (responseData) {
Expand Down Expand Up @@ -259,7 +303,6 @@ - (void)URLSession:(NSURLSession *)session
{
progress = 100.0 * (float)totalBytesSent / (float)totalBytesExpectedToSend;
}

[self _sendEventWithName:@"RNFileUploader-progress" body:@{ @"id": task.taskDescription, @"progress": [NSNumber numberWithFloat:progress] }];
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-background-upload",
"version": "4.2.0",
"version": "4.3.0",
"description": "Cross platform http post file uploader with android and iOS background support",
"main": "index.js",
"scripts": {
Expand Down

0 comments on commit 4513d2b

Please sign in to comment.