Edit AllPages

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

NSURL *myURL = [NSURL URLWithString:@””]; 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 ( )

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 See for det latest version.

source code taken from:


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

gcc -c BatchDownloader.m nm BatchDownloader.o

test: ./batchdownload ~/Desktop/batchdownload


//#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.


@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.


/* This code is licensed in the Public Domain. Please contribute any fixes back to See for det latest version. */

//#import “BatchDownloader.h”

@interface NSObject (PtrValueUtils)

@implementation NSObject (PtrValueUtils)

@interface BatchDownloader (Private)

@implementation BatchDownloader

#pragma mark -


#pragma mark -


// 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];


[urls release];

[pool release]; return 0;