Download a file using cocoa
I want to download a file to the downloads folder. I searched google for this and found the NSURLDownload class. I've read the page in the dev center and created this code (with some copy and pasti开发者_如何转开发ng) this code:
@implementation Downloader
@synthesize downloadResponse;
- (void)startDownloadingURL:(NSString*)downloadUrl destenation:(NSString*)destenation {
// create the request
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:downloadUrl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLDownload *theDownload=[[NSURLDownload alloc] initWithRequest:theRequest
delegate:self];
if (!theDownload) {
NSLog(@"Download could not be made...");
}
}
- (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename {
NSString *destinationFilename;
NSString *homeDirectory=NSHomeDirectory();
destinationFilename=[[homeDirectory stringByAppendingPathComponent:@"Desktop"]
stringByAppendingPathComponent:filename];
[download setDestination:destinationFilename allowOverwrite:NO];
}
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error {
// release the connection
[download release];
// inform the user
NSLog(@"Download failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)downloadDidFinish:(NSURLDownload *)download {
// release the connection
[download release];
// do something with the data
NSLog(@"downloadDidFinish");
}
- (void)setDownloadResponse:(NSURLResponse *)aDownloadResponse {
[aDownloadResponse retain];
[downloadResponse release];
downloadResponse = aDownloadResponse;
}
- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response {
// reset the progress, this might be called multiple times
bytesReceived = 0;
// retain the response to use later
[self setDownloadResponse:response];
}
- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(unsigned)length {
long long expectedLength = [[self downloadResponse] expectedContentLength];
bytesReceived = bytesReceived+length;
if (expectedLength != NSURLResponseUnknownLength) {
percentComplete = (bytesReceived/(float)expectedLength)*100.0;
NSLog(@"Percent - %f",percentComplete);
} else {
NSLog(@"Bytes received - %d",bytesReceived);
}
}
-(NSURLRequest *)download:(NSURLDownload *)download
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse {
NSURLRequest *newRequest=request;
if (redirectResponse) {
newRequest=nil;
}
return newRequest;
}
@end
But my problem is now, it doesn't appear on the desktop as specified. And I want to put it in downloads and not on the desktop... What do I have to do?
EDIT: Last stack:
#0 0x92169ed7 in objc_msgSend
#1 0x01390090 in ??
#2 0x90443107 in URLDownload::didReceiveResponse
#3 0x903ecfc0 in URLConnectionClient::_clientSendDidReceiveResponse
#4 0x90465705 in URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload
#5 0x904658b2 in URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload
#6 0x903e0ace in URLConnectionClient::processEvents
#7 0x903e096f in MultiplexerSource::perform
#8 0x953df15b in __CFRunLoopDoSources0
#9 0x953dcc1f in __CFRunLoopRun
#10 0x953dc0f4 in CFRunLoopRunSpecific
#11 0x953dbf21 in CFRunLoopRunInMode
#12 0x96bc10fc in RunCurrentEventLoopInMode
#13 0x96bc0eb1 in ReceiveNextEventCommon
#14 0x96bc0d36 in BlockUntilNextEventMatchingListInMode
#15 0x9775d135 in _DPSNextEvent
#16 0x9775c976 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
#17 0x9771ebef in -[NSApplication run]
#18 0x97716c85 in NSApplicationMain
#19 0x00002628 in main at main.m:13
You never used that destination string in -startDownloadingURL:destination:
. Presumably you meant to call -[NSURLDownload setDestination:allowOverwrite:]
.
-[NSFileManager URLsForDirectory:NSDownloadsDirectory inDomains:NSUserDomainMask]
should give you a start at getting the downloads directory. I haven't needed to use this method myself, and I think the docs say that it isn't guaranteed that there actually is a directory at the return of the method. So, you need a fallback for that case.
#0 0x92169ed7 in objc_msgSend #1 0x01390090 in ?? #2 0x90443107 in URLDownload::didReceiveResponse
Sounds like you didn't hold on to your Downloader, so it died, and the download then sent a delegate message to your dead Downloader object.
Make sure something keeps on owning the Downloader as long as it needs something downloaded. You can use Instruments's ObjectAlloc instrument to track the creation, retentions, and releases of the Downloader, to see which of the releases you shouldn't be doing.
Don't forget to read or re-read the memory management docs (recently rewritten), while you're at it.
http://allseeing-i.com/ASIHTTPRequest/How-to-use
Hope this will work, it works for me:
-(void)createDownloadContentService:(NSURL *)url{
NSLog(@"URL : %@",url);
NSString *tempFilePath = //Give directory path, make sure its exist and also give file name too, like /Desktop/downloading/filename.zip//;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:tempFilePath]) {
//Not needed if you dont want to resume//
NSURLDownload *download = [[NSURLDownload alloc] initWithResumeData:resumeData delegate:self path:tempFilePath];
[download setDeletesFileUponFailure:NO];
[download setDestination:tempFilePath allowOverwrite:YES];
}else{
NSURLDownload *download = [[NSURLDownload alloc] initWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
[download setDeletesFileUponFailure:NO];
[download setDestination:tempFilePath allowOverwrite:YES];
}
}
implement delegate-----
- (void)downloadDidBegin:(NSURLDownload *)download{
}
- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response{
_totalLength = response.expectedContentLength;
}
- (void)download:(NSURLDownload *)download willResumeWithResponse:(NSURLResponse *)response fromByte:(long long)startingByte{
}
- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(NSUInteger)length{
_recievedLength = _recievedLength + length;
}
- (void)downloadDidFinish:(NSURLDownload *)download{
// Completed, file will be available//
}
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error{
NSLog(@"FAILED DOWNLOAD: %@",[error localizedDescription]);
}
精彩评论