我想在 iPhone 操作系统上使用 Objective-c 直接从 URL 下载文件到磁盘。
目前我正在使用 NSURLConnection 发送同步请求,将返回的 NSData 写入文件。
如何更改下载处理(仍然有同步的请求,它已经在后台线程中)以将数据直接写入磁盘,而不是使用内存变量来存储完整的内容(只有小部分)?
示例代码将不胜感激。
提前感谢大家的回复!
我想在 iPhone 操作系统上使用 Objective-c 直接从 URL 下载文件到磁盘。
目前我正在使用 NSURLConnection 发送同步请求,将返回的 NSData 写入文件。
如何更改下载处理(仍然有同步的请求,它已经在后台线程中)以将数据直接写入磁盘,而不是使用内存变量来存储完整的内容(只有小部分)?
示例代码将不胜感激。
提前感谢大家的回复!
您可以这样做,但设置起来有点复杂。这是我的做法:
警告:以下代码是在浏览器中输入并在我脑海中编译的。此外,没有太多的错误处理。警告实施者。
//NSURLConnection+DirectDownload.h
@interface NSURLConnection (DirectDownload)
+ (BOOL) downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath error:(NSError **)error;
@end
//NSURLConnection+DirectDownload.m
@implementation NSURLConnection (DirectDownload)
+ (BOOL) downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath error:(NSError **)error {
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
//configure the request, or leave it as-is
DirectDownloadDelegate * delegate = [[DirectDownloadDelegate alloc] initWithFilePath:localPath];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
[delegate autorelease];
[request release];
while ([delegate isDone] == NO) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
[connection release];
NSError * downloadError = [delegate error];
if (downloadError != nil) {
if (error != nil) { *error = [[downloadError retain] autorelease]; }
return NO;
}
return YES;
}
//DirectDownloadDelegate.h
@interface DirectDownloadDelegate : NSObject {
NSError *error;
NSURLResponse * response;
BOOL done;
NSFileHandle * outputHandle;
}
@property (readonly, getter=isDone) BOOL done;
@property (readonly) NSError *error;
@property (readonly) NSURLResponse * response;
@end
//DirectDownloadDelegate.m
@implementation DirectDownloadDelegate
@synthesize error, request, done;
- (id) initWithFilePath:(NSString *)path {
if (self = [super init]) {
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
outputHandle = [[NSFileHandle fileHandleForWritingAtPath:path] retain];
}
return self;
}
- (void) dealloc {
[error release];
[response release];
[outputHandle closeFile];
[outputHandle release];
[super dealloc];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)anError {
error = [anError retain];
[self connectionDidFinishLoading:connection];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)someData {
[outputHandle writeData:someData];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse {
response = [aResponse retain];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
done = YES;
}
基本思想是您创建一个标准的NSURLConnection
,通常是异步的,但只需通过自己旋转 runloop 来阻止线程,直到连接完成。您还可以使用自定义 url 连接委托将连接接收到的任何数据直接通过管道传输到文件。
您现在可以执行以下操作:
NSError * downloadError = nil;
BOOL ok = [NSURLConnection downloadItemAtURL:someURL toFile:someFile error:&downloadError];
if (!ok) {
NSLog(@"ack there was an error: %@", error);
} else {
NSLog(@"file downloaded to: %@", someFile);
}