Bunu yapabilirsiniz, ancak kurulumu biraz karmaşıktır. İşte ben şöyle yaparım:
Uyarı: Aşağıdaki kod bir tarayıcıda yazılmıştır ve kafamda derlenmiştir. Ayrıca, çok fazla hata işleme yok. Caveat Uygulayıcısı.
//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;
}
temel fikir normalde asenkron olan standart NSURLConnection
oluşturmak, ama sadece bağlantı yapılana kadar kendinizi runloop iplik ile iplik engellemek olmasıdır. Ayrıca, bağlantının doğrudan bir dosyaya gönderdiği tüm verileri borulamak için özel bir url bağlantısı temsilcisi de kullanabilirsiniz.
Artık yapabilirsiniz:
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);
}
O OS disk dosyasına a` `URL'den bir "kopya veri olmadığı için tam anlamıyla "doğrudan diske" veri indirmek mümkün olacak değil
'' '' bellekten geçmeden '' sistem çağrısı. Veriler, satır boyunca bir yerde hafızaya alınacaktır. Şimdi, "dosyaya indirilen URL" API'si sağlayan bir kütüphane bulmanız mümkündür, ancak dahili olarak hala bellekte bir arabellek kullanıyordur. –
Bu doğru David, ancak dosyaya yazarken tüm dosya içeriğini bellekte saklamak gerekmiyor, sadece küçük tamponlar. Aradığım şey bu. – favo