如何在iOS上下载和解压文件

3
我想下载一个包含mp3文件的zip文件用于我的应用程序。然后,我需要将其解压缩到一个永久目录中,其中包含要按需播放的mp3文件。这是一个词汇应用程序,zip文件包含要提取的mp3文件。该zip文件大小约为5 MB。
更多问题:下载这些文件的好目录是什么?如何进行解压缩?此外,文件或者说它们所在的Web目录受密码保护,因此我需要提供名称和密码。
有人有任何一般性的指导吗?特别是,我想知道如何提供用户名/密码,最佳的下载目录,如何解压缩文件以及如何下载。任何代码示例将不胜感激。
1个回答

6
第一步,要下载受密码保护的文件,您需要一个NSURLConnection,它所在的类需要实现NSURLConnectionDelegate协议以处理身份验证请求。Docs here
为了将它们永久保存,您必须将它们保存到应用程序文档目录中。(请记住,默认情况下,这里的所有文件都会备份到iCloud中,如果在这里有很多MP3,那么iCloud备份大小将过大,苹果可能会因此拒绝您的应用程序。解决方法很简单,只需关闭每个文件的iCloud备份即可)。
接下来,如果您有正确的工具,解压缩就非常简单,我使用Objective-Zip library实现了很好的效果。在Wiki中有一些有用的代码示例,介绍了如何使用它。
因此,在您的情况下,流程将是这样的:
  1. Create an NSURLConnection to the server, providing the username and password when prompted using the authentication challenge delegate methods.
  2. 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];
    }
    
  3. 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!
    
    }
    
  4. 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!


谢谢你的精彩回答!我会试试看。问题是 - 你必须在一个线程中运行它吗? - Jack BeNimble
不用担心!虽然您不必在线程中运行任何内容,但请记住,解压部分不是异步的,因此在运行时会锁定主线程。您可以将其放入NSOperation / GCD队列中,具体取决于您的实现,然后只需要回调侦听器或类似的东西一旦操作完成即可! - andycam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接