CocoaDev

Edit AllPages

A really simple example for downloading files in Cocoa. (Thanks to Austin Shoemaker!)

NSURL *myURL = [NSURL URLWithString:@”http://www.apple.com/”]; NSData *urlContents = [myURL resourceDataUsingCache:YES];

if ([urlContents writeToFile:[@”~/Documents/applewebsite.html” stringByExpandingTildeInPath] atomically:YES]) { // It was successful, do stuff here } else { // There was a problem writing the file }


A slightly more complicated example that will download asynchronously or “in the background” by PeterMonty. I’ve tried to keep it as similar to the one above as possible for comparison.

// Starts download

// This method will be called when the download has finished


Is there anyway of putting a progress indicator to indicate how much it has downloaded?

Yes, read the docs, there is a method that will be called periodically. - SJI


Does anyone know how to cancel loadResourceDataNotifyingClient once it’s started? Alternatively, how about some instructions on using CURLHandle?


I had the same problem loading an image - it kept being loaded from the cache. Using NSURL's resourceDataUsingCache solves the problem and is just as easy - in this case for an image but the URL can be for anything.

NSData *data = NSURL [[URLWithString:myURLString] resourceDataUsingCache:NO]; NSImage *image = [[NSImage alloc] initWithData:data];


For those with more advanced needs, CURLHandle by Dan Wood comes highly recommended ( http://curlhandle.sourceforge.net/ )


I highly recommend CURLHandle even for non-advanced needs. There are times when NSURL just won’t do. For example, I’ve often found it has trouble downloading The Mac Observer and a few other sites.


I’m using code basically the same as the asynchronous example above. I also catch - URL: resourceDataDidBecomeAvailable: to display progress while the file is loading. But even though I have UsingCache:YES in both places, when I step over the line:

NSData *urlContents = [sender resourceDataUsingCache:YES];

The file is downloaded all over again… at least, I assume it is, because it takes ages to execute that one statement, during which time there is a lot of network activity. Has anyone come across that problem before? – AngelaBrett


Here’s yet another snippet showing how to batch download files.

/*

This code is licensed in the Public Domain. Please contribute any fixes back to hakan@konstochvanligasaker.se See http://konstochvanligasaker.se/code for det latest version.

source code taken from: http://konstochvanligasaker.se/code/src/BatchDownloader.h http://konstochvanligasaker.se/code/src/BatchDownloader.m

patches:

compile with: gcc -Wall -framework Foundation -o batchdownload BatchDownloader.m

gcc -c BatchDownloader.m nm BatchDownloader.o

test: ./batchdownload ~/Desktop/batchdownload http://www.google.com http://www.apple.com

*/

//#import <Cocoa/Cocoa.h> #import <Foundation/Foundation.h>

@interface NSObject (BatchDownloaderDelegate)

// fired when one or more downloads are ready. The array contains a dictionary // with URLs as the keys, and the local file paths as the keys.

// array of URLs that could not be downloaded.

@end

@interface BatchDownloader : NSObject { // fast (constant-time) lookup for a URL, just given a download object. // unfortunately we can’t just use a dictionary with NSURLDownloads as keys, because it doesn’t // implement the NSCopying protocol. NSMutableDictionary *downloadPtrsToURLs;

// URL => NSURLDownload NSMutableDictionary *downloadURLsToObjects;

// URL => local file path NSMutableDictionary *downloadURLsToLocalPaths;

id delegate;

NSString *destinationFolder; }

// will try to create dest folder if it doesn’t exist.

@end

/* This code is licensed in the Public Domain. Please contribute any fixes back to hakan@konstochvanligasaker.se See http://konstochvanligasaker.se/code for det latest version. */

//#import “BatchDownloader.h”

@interface NSObject (PtrValueUtils)

@implementation NSObject (PtrValueUtils)

@interface BatchDownloader (Private)

@implementation BatchDownloader

#pragma mark -

}

#pragma mark -

@end

// ADDED int main(int argc, const char *argv[]) {

if (argc < 3) return 1;

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSMutableArray *commandLineArguments = [NSMutableArray arrayWithArray:[[NSProcessInfo processInfo] arguments]]; [commandLineArguments removeObjectAtIndex: 0]; // first object is the name of the executable

NSString *destFolder = [commandLineArguments objectAtIndex: 0]; [commandLineArguments removeObjectAtIndex: 0];

BatchDownloader *urls = [[BatchDownloader alloc] init]; [urls initWithDestinationFolder:destFolder delegate:urls ]; [urls addDownloads: commandLineArguments];

CFRunLoopRun();

[urls release];

[pool release]; return 0;

}