/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #import "RCTFileRequestHandler.h" #import #import @implementation RCTFileRequestHandler { NSOperationQueue *_fileQueue; } RCT_EXPORT_MODULE() - (void)invalidate { [_fileQueue cancelAllOperations]; _fileQueue = nil; } - (BOOL)canHandleRequest:(NSURLRequest *)request { return [request.URL.scheme caseInsensitiveCompare:@"file"] == NSOrderedSame && !RCTIsBundleAssetURL(request.URL); } - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate { // Lazy setup if (!_fileQueue) { _fileQueue = [NSOperationQueue new]; _fileQueue.maxConcurrentOperationCount = 4; } __weak __block NSBlockOperation *weakOp; __block NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ // Get content length NSError *error = nil; NSFileManager *fileManager = [NSFileManager new]; NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:request.URL.path error:&error]; if (!fileAttributes) { [delegate URLRequest:weakOp didCompleteWithError:error]; return; } // Get mime type NSString *fileExtension = [request.URL pathExtension]; NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag( kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL); NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass( (__bridge CFStringRef)UTI, kUTTagClassMIMEType); // Send response NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:contentType expectedContentLength:[fileAttributes[NSFileSize] ?: @-1 integerValue] textEncodingName:nil]; [delegate URLRequest:weakOp didReceiveResponse:response]; // Load data NSData *data = [NSData dataWithContentsOfURL:request.URL options:NSDataReadingMappedIfSafe error:&error]; if (data) { [delegate URLRequest:weakOp didReceiveData:data]; } [delegate URLRequest:weakOp didCompleteWithError:error]; }]; weakOp = op; [_fileQueue addOperation:op]; return op; } - (void)cancelRequest:(NSOperation *)op { [op cancel]; } @end