Last active
July 8, 2016 15:23
-
-
Save Elyx0/5dc53bef294b42c847f1baea7cc5e911 to your computer and use it in GitHub Desktop.
RNRF Uploader.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "Uploader.h" | |
#import "RCTLog.h" | |
@implementation UploadParams | |
@end | |
@interface Uploader() | |
@property (copy) UploadParams* params; | |
@property (retain) NSURLSessionDataTask* task; | |
@end | |
@implementation Uploader | |
- (void)uploadFiles:(UploadParams*)params | |
{ | |
_params = params; | |
NSString *method = _params.method; | |
NSURL *url = [NSURL URLWithString:_params.toUrl]; | |
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url]; | |
[req setHTTPMethod:method]; | |
// set headers | |
NSString *formBoundaryString = [self generateBoundaryString]; | |
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", formBoundaryString]; | |
[req setValue:contentType forHTTPHeaderField:@"Content-Type"]; | |
for (NSString *key in _params.headers) { | |
id val = [_params.headers objectForKey:key]; | |
if ([val respondsToSelector:@selector(stringValue)]) { | |
val = [val stringValue]; | |
} | |
if (![val isKindOfClass:[NSString class]]) { | |
continue; | |
} | |
[req setValue:val forHTTPHeaderField:key]; | |
} | |
NSData *formBoundaryData = [[NSString stringWithFormat:@"--%@\r\n", formBoundaryString] dataUsingEncoding:NSUTF8StringEncoding]; | |
NSMutableData* reqBody = [NSMutableData data]; | |
// add fields | |
for (NSString *key in _params.fields) { | |
id val = [_params.fields objectForKey:key]; | |
if ([val respondsToSelector:@selector(stringValue)]) { | |
val = [val stringValue]; | |
} | |
if (![val isKindOfClass:[NSString class]]) { | |
continue; | |
} | |
[reqBody appendData:formBoundaryData]; | |
[reqBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]]; | |
[reqBody appendData:[val dataUsingEncoding:NSUTF8StringEncoding]]; | |
[reqBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; | |
} | |
// add files | |
for (NSDictionary *file in _params.files) { | |
NSString *name = file[@"name"]; | |
NSString *filename = file[@"filename"]; | |
NSString *filepath = file[@"filepath"]; | |
NSString *filetype = file[@"filetype"]; | |
// http://stackoverflow.com/questions/8809054/fileexistsatpath-returns-no-for-a-directory-that-exists?rq=1 | |
// NSData *fileData = [NSData dataWithContentsOfFile:filepath]; | |
[reqBody appendData:formBoundaryData]; | |
[reqBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name.length ? name : filename, filename] dataUsingEncoding:NSUTF8StringEncoding]]; | |
if (filetype) { | |
[reqBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n", filetype] dataUsingEncoding:NSUTF8StringEncoding]]; | |
} else { | |
[reqBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n", [self mimeTypeForPath:filename]] dataUsingEncoding:NSUTF8StringEncoding]]; | |
} | |
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filepath]; | |
[fileURL startAccessingSecurityScopedResource]; | |
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init]; | |
NSError *error; | |
__block NSData *fileData; | |
[coordinator coordinateReadingItemAtURL:fileURL options:NSFileCoordinatorReadingForUploading error:&error byAccessor:^(NSURL *newURL) { | |
NSError *fileConversionError; | |
fileData = [NSData dataWithContentsOfURL:newURL options:NSDataReadingUncached error:&fileConversionError]; | |
if ([fileData length] == 0) { | |
NSError *error = [NSError errorWithDomain:@"com.darwineco.ppim" code:77 userInfo:[NSDictionary dictionaryWithObject:@"empty" forKey:NSLocalizedDescriptionKey]]; | |
_params.errorCallback(error); | |
return; | |
} | |
[self doUpload:reqBody :fileData :req :formBoundaryString]; | |
}]; | |
[fileURL stopAccessingSecurityScopedResource]; | |
} | |
} | |
- (void)doUpload:(NSMutableData*) reqBody | |
:(NSData*) fileData | |
:(NSMutableURLRequest*) req | |
:(NSString*) formBoundaryString | |
{ | |
[reqBody appendData:[[NSString stringWithFormat:@"Content-Length: %ld\r\n\r\n", (long)[fileData length]] dataUsingEncoding:NSUTF8StringEncoding]]; | |
[reqBody appendData:fileData]; | |
[reqBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; | |
// add end boundary | |
NSData* end = [[NSString stringWithFormat:@"--%@--\r\n", formBoundaryString] dataUsingEncoding:NSUTF8StringEncoding]; | |
[reqBody appendData:end]; | |
// send request | |
[req setHTTPBody:reqBody]; | |
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; | |
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:(id)self delegateQueue:[NSOperationQueue mainQueue]]; | |
_task = [session dataTaskWithRequest:req]; | |
[_task resume]; | |
_params.beginCallback(); | |
} | |
- (NSString *)generateBoundaryString | |
{ | |
NSString *uuid = [[NSUUID UUID] UUIDString]; | |
return [NSString stringWithFormat:@"----%@", uuid]; | |
} | |
- (NSString *)mimeTypeForPath:(NSString *)filepath | |
{ | |
NSString *fileExtension = [filepath pathExtension]; | |
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL); | |
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType); | |
if (contentType) { | |
return contentType; | |
} | |
return @"application/octet-stream"; | |
} | |
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error | |
{ | |
if(error != nil) { | |
return _params.errorCallback(error); | |
} | |
} | |
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend | |
{ | |
return _params.progressCallback([NSNumber numberWithLongLong:totalBytesExpectedToSend], [NSNumber numberWithLongLong:totalBytesSent]); | |
} | |
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data | |
{ | |
NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; | |
return _params.completeCallback(str); | |
} | |
- (void)stopUpload | |
{ | |
[_task cancel]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment