2012-07-23 53 views
3

我想下载包含适用于我的应用程序的mp3的zip文件。然后,我需要将其解压缩到一个永久目录中,该目录将包含要按需播放的MP3。这是一个词汇应用程序,zip文件包含要提取的mp3。该zip文件约为5 MB。如何在iOS上下载和解压缩文件

更多问题:什么是一个很好的目录将这些下载到?如何解压缩?此外,这些文件或者说他们所在的网页目录是受密码保护的,所以我需要提供名称和密码。

有没有人有任何一般的指针?特别是,我想知道如何提供用户名/密码,要下载的最佳目录,如何解压缩文件以及如何下载。任何代码示例将不胜感激。

回答

6

第一步,为了下载受密码保护的文件,你需要一个NSURLConnection类,它需要实现NSURLConnectionDelegate协议来处理认证请求。 Docs here

为了永久保存这些,你必须将它们保存到应用程序文件目录。 (请记住,默认情况下,这里的所有文件都备份到iCloud,在这里有很多MP3会导致iCloud备份太大,Apple可能会拒绝你的应用程序,简单的解决方法是关闭iCloud备份您下载/解压到文档目录的每个文件)。

接下来,解压缩是相当简单的,如果你有合适的工具,我已经实现这个使用Objective-Zip library巨大的成功。 Wiki中的一些方便的代码示例使用了这个。

所以你的情况,该过程将沿着线:

  1. 创建NSURLConnection到服务器,使用认证挑战委托方法提示时提供的用户名和密码。
  2. 使用NSURLConnection的下载类似于下面的代码块的代表。 将接收到的字节附加到磁盘上的文件中是比较安全的做法(而不是将它附加到NSMutableData对象),如果您的zip文件太大而不能完全保留在内存中,您将遇到频繁的崩溃。

    // 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. 现在你已经完全下载ZipFile中,使用它的Objective-ZIP,应该是这个样子(再解压缩,这种方法是伟大的,因为它会缓存文件,这样即使是大文件解压缩不该”牛逼导致内存问题)

    -(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. 现在应该把解压缩下载的zip文件的文件目录的您所需的子文件夹,这些文件就可以使用了!

+0

感谢伟大的答案!我会试试看。问题 - 你必须在一个线程中运行它吗? – 2012-07-23 11:32:36

+0

不用担心!虽然你不必在一个线程中运行这些任务,但要记住解压缩的部分不是异步的,所以在运行时会锁定主线程。你当然可以把它放在一个NSOperation/GCD队列中,这取决于你的实现,然后你只需要一个回调监听器或类似的东西,一旦操作完成! – andycam 2012-07-23 23:26:26