mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Begin implementation of NSURLSessionDownloadTask
This commit is contained in:
parent
99ef0c9665
commit
d3e40dfc9d
4 changed files with 155 additions and 9 deletions
|
@ -24,6 +24,7 @@
|
|||
@class NSURLResponse;
|
||||
@class NSURLSessionConfiguration;
|
||||
@class NSURLSessionDataTask;
|
||||
@class NSURLSessionDownloadTask;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -110,6 +111,12 @@ GS_EXPORT_CLASS
|
|||
/* Creates a data task to retrieve the contents of the given URL. */
|
||||
- (NSURLSessionDataTask*) dataTaskWithURL: (NSURL*)url;
|
||||
|
||||
/* Creates a download task with the given request. */
|
||||
- (NSURLSessionDownloadTask *) downloadTaskWithRequest: (NSURLRequest *)request;
|
||||
|
||||
/* Creates a download task to download the contents of the given URL. */
|
||||
- (NSURLSessionDownloadTask *) downloadTaskWithURL: (NSURL *)url;
|
||||
|
||||
@end
|
||||
|
||||
typedef NS_ENUM(NSUInteger, NSURLSessionTaskState) {
|
||||
|
@ -430,6 +437,37 @@ didReceiveChallenge: (NSURLAuthenticationChallenge*)challenge
|
|||
|
||||
@end
|
||||
|
||||
@protocol NSURLSessionDownloadDelegate <NSURLSessionTaskDelegate>
|
||||
|
||||
/* Sent when a download task that has completed a download. The delegate should
|
||||
* copy or move the file at the given location to a new location as it will be
|
||||
* removed when the delegate message returns. URLSession:task:didCompleteWithError: will
|
||||
* still be called.
|
||||
*/
|
||||
- (void) URLSession: (NSURLSession *)session
|
||||
downloadTask: (NSURLSessionDownloadTask *)downloadTask
|
||||
didFinishDownloadingToURL: (NSURL *)location;
|
||||
|
||||
@optional
|
||||
/* Sent periodically to notify the delegate of download progress. */
|
||||
- (void) URLSession: (NSURLSession *)session
|
||||
downloadTask: (NSURLSessionDownloadTask *)downloadTask
|
||||
didWriteData: (int64_t)bytesWritten
|
||||
totalBytesWritten: (int64_t)totalBytesWritten
|
||||
totalBytesExpectedToWrite: (int64_t)totalBytesExpectedToWrite;
|
||||
|
||||
/* Sent when a download has been resumed. If a download failed with an
|
||||
* error, the -userInfo dictionary of the error will contain an
|
||||
* NSURLSessionDownloadTaskResumeData key, whose value is the resume
|
||||
* data.
|
||||
*/
|
||||
- (void) URLSession: (NSURLSession *)session
|
||||
downloadTask: (NSURLSessionDownloadTask *)downloadTask
|
||||
didResumeAtOffset: (int64_t)fileOffset
|
||||
expectedTotalBytes: (int64_t)expectedTotalBytes;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#import "Foundation/NSURL.h"
|
||||
#import "Foundation/NSURLError.h"
|
||||
#import "Foundation/NSURLSession.h"
|
||||
#import "Foundation/NSFileHandle.h"
|
||||
|
||||
|
||||
static BOOL isEasyHandlePaused(GSNativeProtocolInternalState state)
|
||||
|
@ -97,6 +98,8 @@ static BOOL isEasyHandleAddedToMultiHandle(GSNativeProtocolInternalState state)
|
|||
|
||||
- (void) setError: (NSError*)error;
|
||||
|
||||
- (void) setCountOfBytesReceived: (int64_t)count;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSURLSessionTask (Internal)
|
||||
|
@ -138,6 +141,11 @@ static BOOL isEasyHandleAddedToMultiHandle(GSNativeProtocolInternalState state)
|
|||
ASSIGN(_error, error);
|
||||
}
|
||||
|
||||
- (void) setCountOfBytesReceived: (int64_t)count
|
||||
{
|
||||
_countOfBytesReceived = count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GSCompletionAction
|
||||
|
@ -493,13 +501,16 @@ static BOOL isEasyHandleAddedToMultiHandle(GSNativeProtocolInternalState state)
|
|||
|
||||
- (void) notifyDelegateAboutReceivedData: (NSData*)data
|
||||
{
|
||||
NSURLSessionTask *task;
|
||||
id<NSURLSessionDelegate> delegate;
|
||||
NSURLSession *session;
|
||||
NSURLSessionTask *task;
|
||||
id<NSURLSessionDelegate> delegate;
|
||||
|
||||
task = [self task];
|
||||
|
||||
NSAssert(nil != task, @"Cannot notify");
|
||||
|
||||
session = [task session];
|
||||
NSAssert(nil != session, @"Missing session");
|
||||
|
||||
delegate = [[task session] delegate];
|
||||
if (nil != delegate
|
||||
&& [task isKindOfClass: [NSURLSessionDataTask class]]
|
||||
|
@ -507,10 +518,7 @@ static BOOL isEasyHandleAddedToMultiHandle(GSNativeProtocolInternalState state)
|
|||
{
|
||||
id<NSURLSessionDataDelegate> dataDelegate;
|
||||
NSURLSessionDataTask *dataTask;
|
||||
NSURLSession *session;
|
||||
|
||||
session = [task session];
|
||||
NSAssert(nil != session, @"Missing session");
|
||||
|
||||
dataDelegate = (id<NSURLSessionDataDelegate>)delegate;
|
||||
dataTask = (NSURLSessionDataTask*)task;
|
||||
[[session delegateQueue] addOperationWithBlock:
|
||||
|
@ -520,6 +528,40 @@ static BOOL isEasyHandleAddedToMultiHandle(GSNativeProtocolInternalState state)
|
|||
didReceiveData: data];
|
||||
}];
|
||||
}
|
||||
/* Don't check whether delegate respondsToSelector.
|
||||
* This delegate is optional. */
|
||||
if (nil != delegate
|
||||
&& [task isKindOfClass: [NSURLSessionDownloadTask class]])
|
||||
{
|
||||
id<NSURLSessionDownloadDelegate> downloadDelegate;
|
||||
NSURLSessionDownloadTask *downloadTask;
|
||||
GSDataDrain *dataDrain;
|
||||
NSFileHandle *fileHandle;
|
||||
|
||||
downloadDelegate = (id<NSURLSessionDownloadDelegate>)delegate;
|
||||
downloadTask = (NSURLSessionDownloadTask*)task;
|
||||
dataDrain = [_transferState bodyDataDrain];
|
||||
|
||||
/* Write to file. GSDataDrain opens the fileHandle. */
|
||||
fileHandle = [dataDrain fileHandle];
|
||||
[fileHandle seekToEndOfFile];
|
||||
[fileHandle writeData: data];
|
||||
|
||||
if ([delegate respondsToSelector: @selector
|
||||
(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)])
|
||||
{
|
||||
/* Calculate received data length */
|
||||
[task setCountOfBytesReceived: (int64_t)[data length] + [task countOfBytesReceived]];
|
||||
[[session delegateQueue] addOperationWithBlock:
|
||||
^{
|
||||
[downloadDelegate URLSession: session
|
||||
downloadTask: downloadTask
|
||||
didWriteData: (int64_t)[data length]
|
||||
totalBytesWritten: [task countOfBytesReceived]
|
||||
totalBytesExpectedToWrite: [task countOfBytesExpectedToReceive]];
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) notifyDelegateAboutUploadedDataCount: (int64_t)count
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#import "Foundation/NSURLError.h"
|
||||
#import "Foundation/NSURLResponse.h"
|
||||
#import "Foundation/NSURLSession.h"
|
||||
#import "Foundation/NSUUID.h"
|
||||
#import "Foundation/NSFileManager.h"
|
||||
#import "Foundation/NSPathUtilities.h"
|
||||
|
||||
#define GS_DELIMITERS_CR 0x0d
|
||||
#define GS_DELIMITERS_LR 0x0a
|
||||
|
@ -277,6 +280,25 @@
|
|||
|
||||
- (NSURL*) fileURL
|
||||
{
|
||||
/* Generate a random fileURL if fileURL is not initialized.
|
||||
* It would be nice to have this implemented in an initializer. */
|
||||
if (!_fileURL)
|
||||
{
|
||||
NSUUID *randomUUID;
|
||||
NSString *fileName;
|
||||
NSURL *tempURL;
|
||||
|
||||
randomUUID = [NSUUID UUID];
|
||||
fileName = [[randomUUID UUIDString] stringByAppendingPathExtension: @"tmp"];
|
||||
tempURL = [NSURL fileURLWithPath: NSTemporaryDirectory()];
|
||||
|
||||
_fileURL = [NSURL fileURLWithPath: fileName relativeToURL: tempURL];
|
||||
|
||||
RELEASE(randomUUID);
|
||||
RELEASE(fileName);
|
||||
RELEASE(tempURL);
|
||||
}
|
||||
|
||||
return _fileURL;
|
||||
}
|
||||
|
||||
|
@ -287,6 +309,17 @@
|
|||
|
||||
- (NSFileHandle*) fileHandle
|
||||
{
|
||||
/* Create temporary file and open a fileHandle for writing. */
|
||||
if (!_fileHandle)
|
||||
{
|
||||
NSFileManager *file = [NSFileManager defaultManager];
|
||||
[file createFileAtPath: [[self fileURL] relativePath] contents: nil attributes: nil];
|
||||
|
||||
_fileHandle = [NSFileHandle fileHandleForWritingToURL: [self fileURL] error: NULL];
|
||||
|
||||
RELEASE(file);
|
||||
}
|
||||
|
||||
return _fileHandle;
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,34 @@ static int nextSessionIdentifier()
|
|||
return [self dataTaskWithRequest: request];
|
||||
}
|
||||
|
||||
- (NSURLSessionDownloadTask *) downloadTaskWithRequest: (NSURLRequest *)request
|
||||
{
|
||||
NSURLSessionDownloadTask *task;
|
||||
|
||||
if (_invalidated)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
task = [[NSURLSessionDownloadTask alloc] initWithSession: self
|
||||
request: request
|
||||
taskIdentifier: _nextTaskIdentifier++];
|
||||
|
||||
[self addTask: task];
|
||||
|
||||
return AUTORELEASE(task);
|
||||
}
|
||||
|
||||
- (NSURLSessionDownloadTask *) downloadTaskWithURL: (NSURL *)url
|
||||
{
|
||||
NSMutableURLRequest *request;
|
||||
|
||||
request = [NSMutableURLRequest requestWithURL: url];
|
||||
[request setHTTPMethod: @"GET"];
|
||||
|
||||
return [self downloadTaskWithRequest: request];
|
||||
}
|
||||
|
||||
- (void) addTask: (NSURLSessionTask*)task
|
||||
{
|
||||
[_taskRegistry addTask: task];
|
||||
|
@ -632,7 +660,7 @@ static int nextSessionIdentifier()
|
|||
|
||||
@implementation NSURLSessionTask
|
||||
{
|
||||
NSURLSession *_session; /* not retained */
|
||||
NSURLSession *_session;
|
||||
NSLock *_protocolLock;
|
||||
NSURLSessionTaskProtocolState _protocolState;
|
||||
NSURLProtocol *_protocol;
|
||||
|
@ -653,7 +681,7 @@ static int nextSessionIdentifier()
|
|||
NSData *data;
|
||||
NSInputStream *stream;
|
||||
|
||||
_session = session;
|
||||
ASSIGN(_session, session);
|
||||
ASSIGN(_originalRequest, request);
|
||||
ASSIGN(_currentRequest, request);
|
||||
if ([(data = [request HTTPBody]) length] > 0)
|
||||
|
@ -694,6 +722,7 @@ static int nextSessionIdentifier()
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(_session);
|
||||
DESTROY(_originalRequest);
|
||||
DESTROY(_currentRequest);
|
||||
DESTROY(_response);
|
||||
|
@ -1083,6 +1112,10 @@ static int nextSessionIdentifier()
|
|||
|
||||
@end
|
||||
|
||||
@implementation NSURLSessionDownloadTask
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSURLSessionConfiguration
|
||||
|
||||
static NSURLSessionConfiguration *def = nil;
|
||||
|
|
Loading…
Reference in a new issue