Skip to content

Instantly share code, notes, and snippets.

@Elyx0
Last active July 8, 2016 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Elyx0/5dc53bef294b42c847f1baea7cc5e911 to your computer and use it in GitHub Desktop.
Save Elyx0/5dc53bef294b42c847f1baea7cc5e911 to your computer and use it in GitHub Desktop.
RNRF Uploader.m
#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