如何将文件直接下载到iPhone os上的磁盘? [英] How to download files directly to disk on the iPhone os?
问题描述
目前我正在使用NSURLConnection发送一个synchronizationRequest,将返回的NSData写入一个文件。
如何更改下载处理(仍然有请求同步,它已经在后台线程中)写入数据直接到磁盘,不使用内存变量存储完整的内容(只有小部分)?
一个示例代码将不胜感激。
谢谢你们的回复!
你可以这样做,但有点复杂建立。以下是我如何做:
警告:以下代码是在浏览器中输入并编译在我的头上。此外,还没有很多错误处理。警告实施者
// NSURLConnection + DirectDownload.h
@interface NSURLConnection(DirectDownload)
+(BOOL)downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath错误:(NSError **)错误;
@end
//NSURLConnection+DirectDownload.m
@implementation NSURLConnection(DirectDownload)
+(BOOL)downloadItemAtURL :( NSURL *)url toFile:(NSString *)localPath错误:(NSError **)错误{
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
//配置请求,或者将它保留为
DirectDownloadDelegate * delegate = [[DirectDownloadDelegate alloc] initWithFilePath:localPath];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
[delegate autorelease];
[请求发布];
while([delegate isDone] == NO){
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
[连接发布];
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完成;
NSFileHandle * outputHandle;
}
@property(readonly,getter = isDone)BOOL done;
@property(readonly)NSError *错误;
@property(readonly)NSURLResponse * response;
@end
//DirectDownloadDelegate.m
@implementation DirectDownloadDelegate
@synthesize错误,请求,完成;
- (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 {
[错误发布];
[response release];
[outputHandle closeFile];
[outputHandle release];
[super dealloc];
}
- (void)连接:(NSURLConnection *)连接didFailWithError:(NSError *)anError {
error = [anError retain];
[self connectionDidFinishLoading:connection];
}
- (void)连接:(NSURLConnection *)连接didReceiveData:(NSData *)someData {
[outputHandle writeData:someData];
}
- (void)connection:(NSURLConnection *)连接didReceiveResponse :( NSURLResponse *)aResponse {
response = [aResponse retain];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)连接{
done = YES;
}
基本思想是创建一个标准的 NSURLConnection
,通常是异步的,但是只能通过自己的旋转来阻止线程,直到连接完成为止。您还可以使用自定义网址连接代理管理连接直接接收到文件的任何数据。
您现在可以执行以下操作:
NSError * downloadError = nil;
BOOL ok = [NSURLConnection downloadItemAtURL:someURL toFile:someFile error:& downloadError];
if(!ok){
NSLog(@ack有错误:%@,错误);
} else {
NSLog(@文件下载到:%@,someFile);
}
I would like to download files directly from an URL to the disk using objective-c on the iPhone os.
Currently I am using NSURLConnection to send a synchronousRequest, writing the returned NSData into a file.
How can I change the download handling (still having the request beeing synchronous, it is already in a background thread) to write the data directly to disk, not using memory variables to store the complete content (only small parts)?
A sample code would be appreciated.
Thank you all in advance for your responses!
You can do this, but it's a bit complicated to set up. Here's how I'd do it:
warning: the following code was typed in a browser and compiled in my head. Also, there's not a lot of error handling. Caveat Implementor.
//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;
}
The basic idea is that you create a standard NSURLConnection
, which is normally asynchronous, but just block the thread by spinning the runloop yourself until the connection is done. You also use a custom url connection delegate to just pipe any data the connection receives directly to a file.
You can now do:
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);
}
这篇关于如何将文件直接下载到iPhone os上的磁盘?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!