I\'d like to download a zip file containing mp3s for my app. Then, I will need to unzip it into a permanent directory, which will contain the mp3s to be played on demand. This i
First step, to download password protected files you need an NSURLConnection, the class it's in needs to implement the NSURLConnectionDelegate
protocol in order to handle authentication requests. Docs here.
In order to store these permanently, you have to save them to the app Documents directory. (Bear in mind that by default all files in here are backed up to iCloud, having lots of MP3s in here will drive the iCloud backup size too far and Apple may reject your app for that. Simple fix for this is to just turn off iCloud backup for each file you download/unzip to your documents directory).
Next, unzipping is fairly straightforward if you have the right tools, I've had great success implementing this using the Objective-Zip library. Some handy code samples in the Wiki on the usage of this.
So in your case, the process will be along the lines of:
NSURLConnection
to the server, providing the username and password when prompted using the authentication challenge delegate methods.Use the NSURLConnection download delegates similar to the below code block. It's safer practice to append the received bytes to the file on disk as you receive it (rather than keep appending it to an NSMutableData object), if your zip files are too large to keep entirely in memory you'll experience frequent crashes.
// Once we have the authenticated connection, handle the received file download:
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Attempt to open the file and write the downloaded data to it
if (![fileManager fileExistsAtPath:currentDownload]) {
[fileManager createFileAtPath:currentDownload contents:nil attributes:nil];
}
// Append data to end of file
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:currentDownload];
[fileHandle seekToEndOfFile];
[fileHandle writeData:data];
[fileHandle closeFile];
}
Now you have the completely downloaded ZipFile, unzip it using Objective-Zip, should look something like this (Again, this method is great because it buffers the file so even large files to unzip shouldn't cause memory issues!):
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
// I set buffer size to 2048 bytes, YMMV so feel free to adjust this
#define BUFFER_SIZE 2048
ZipFile *unzipFile = [[ZipFile alloc] initWithFileName:zipFilePath mode:ZipFileModeUnzip];
NSMutableData *unzipBuffer = [NSMutableData dataWithLength:BUFFER_SIZE];
NSArray *fileArray = [unzipFile listFileInZipInfos];
NSFileHandle *fileHandle;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *targetFolder = folderToUnzipToGoesHere;
[unzipFile goToFirstFileInZip];
// For each file in the zipped file...
for (NSString *file in fileArray) {
// Get the file info/name, prepare the target name/path
ZipReadStream *readStream = [unzipFile readCurrentFileInZip];
FileInZipInfo *fileInfo = [unzipFile getCurrentFileInZipInfo];
NSString *fileName = [fileInfo name];
NSString *unzipFilePath = [targetFolder stringByAppendingPathComponent:fileName];
// Create a file handle for writing the unzipped file contents
if (![fileManager fileExistsAtPath:unzipFilePath]) {
[fileManager createFileAtPath:unzipFilePath contents:nil attributes:nil];
}
fileHandle = [NSFileHandle fileHandleForWritingAtPath:unzipFilePath];
// Read-then-write buffered loop to conserve memory
do {
// Reset buffer length
[unzipBuffer setLength:BUFFER_SIZE];
// Expand next chunk of bytes
int bytesRead = [readStream readDataWithBuffer:unzipBuffer];
if (bytesRead > 0) {
// Write what we have read
[unzipBuffer setLength:bytesRead];
[fileHandle writeData:unzipBuffer];
} else
break;
} while (YES);
[readStream finishedReading];
[fileHandle closeFile];
// NOTE: Disable iCloud backup for unzipped file if applicable here!
/*...*/
[unzipFile goToNextFileInZip];
}
[unzipFile close]; // Be sure to also manage your memory manually if not using ARC!
// Also delete the zip file here to conserve disk space if applicable!
}
You should now have unzipped the downloaded zip file to your desired sub-folder of the Documents directory, and the files are ready to be used!