diff --git a/SSZipArchive/SSZipArchive.h b/SSZipArchive/SSZipArchive.h index 9cdf29e..9546b77 100644 --- a/SSZipArchive/SSZipArchive.h +++ b/SSZipArchive/SSZipArchive.h @@ -46,6 +46,7 @@ - (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo; - (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo; +- (void)zipArchiveProgressEvent:(NSInteger)loaded total:(NSInteger)total; @end #endif /* _SSZIPARCHIVE_H */ diff --git a/SSZipArchive/SSZipArchive.m b/SSZipArchive/SSZipArchive.m index 22c6726..8384ede 100644 --- a/SSZipArchive/SSZipArchive.m +++ b/SSZipArchive/SSZipArchive.m @@ -55,6 +55,10 @@ return NO; } + NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil]; + ZPOS64_T fileSize = fileAttributes.fileSize; + ZPOS64_T currentPosition = 0; + unz_global_info globalInfo = {0ul, 0ul}; unzGetGlobalInfo(zip, &globalInfo); @@ -77,6 +81,9 @@ if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipArchiveAtPath:zipInfo:)]) { [delegate zipArchiveWillUnzipArchiveAtPath:path zipInfo:globalInfo]; } + if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) { + [delegate zipArchiveProgressEvent:currentPosition total:fileSize]; + } NSInteger currentFileNumber = 0; do { @@ -103,11 +110,16 @@ break; } + currentPosition += fileInfo.compressed_size; + // Message delegate if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) { [delegate zipArchiveWillUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry archivePath:path fileInfo:fileInfo]; } + if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) { + [delegate zipArchiveProgressEvent:currentPosition total:fileSize]; + } char *filename = (char *)malloc(fileInfo.size_filename + 1); unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0); @@ -221,6 +233,10 @@ // Unable to set the permissions attribute NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions"); } + +#if !__has_feature(objc_arc) + [attrs release]; +#endif } } } @@ -282,6 +298,10 @@ if (success && [delegate respondsToSelector:@selector(zipArchiveDidUnzipArchiveAtPath:zipInfo:unzippedPath:)]) { [delegate zipArchiveDidUnzipArchiveAtPath:path zipInfo:globalInfo unzippedPath:destination]; } + // final progress event = 100% + if ([delegate respondsToSelector:@selector(zipArchiveProgressEvent:total:)]) { + [delegate zipArchiveProgressEvent:fileSize total:fileSize]; + } return success; } diff --git a/SSZipArchive/minizip/unzip.c b/SSZipArchive/minizip/unzip.c index b90868e..d82f184 100755 --- a/SSZipArchive/minizip/unzip.c +++ b/SSZipArchive/minizip/unzip.c @@ -1514,6 +1514,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; pfile_in_zip_read_info->raw=raw; + pfile_in_zip_read_info->byte_before_the_zipfile = 0; if (pfile_in_zip_read_info->read_buffer==NULL) { diff --git a/Tests/SSZipArchiveTests.m b/Tests/SSZipArchiveTests.m index 7497668..df43385 100644 --- a/Tests/SSZipArchiveTests.m +++ b/Tests/SSZipArchiveTests.m @@ -13,7 +13,14 @@ @interface SSZipArchiveTests : XCTestCase @end -@implementation SSZipArchiveTests +@implementation SSZipArchiveTests { + NSMutableArray *progressEvents; +} + +- (void)setUp { + [super setUp]; + progressEvents = [NSMutableArray array]; +} - (void)tearDown { [super tearDown]; @@ -65,6 +72,22 @@ XCTAssertTrue([fileManager fileExistsAtPath:testPath], @"LICENSE unzipped"); } +- (void)testUnzippingProgress { + NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"]; + NSString *outputPath = [self _cachesPath:@"Progress"]; + + [progressEvents removeAllObjects]; + + [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self]; + + // 4 events: the first, then for each of the two files one, then the final event + XCTAssertTrue(4 == [progressEvents count], @"Expected 4 progress events"); + XCTAssertTrue(0 == [[progressEvents objectAtIndex:0] intValue]); + XCTAssertTrue(619 == [[progressEvents objectAtIndex:1] intValue]); + XCTAssertTrue(1114 == [[progressEvents objectAtIndex:2] intValue]); + XCTAssertTrue(1436 == [[progressEvents objectAtIndex:3] intValue]); +} + - (void)testUnzippingWithPassword { NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestPasswordArchive" ofType:@"zip"]; @@ -252,12 +275,17 @@ - (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo { - NSLog(@"*** zipArchiveWillUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", fileIndex, totalFiles, archivePath); + NSLog(@"*** zipArchiveWillUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", (int)fileIndex, (int)totalFiles, archivePath); } - (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo { - NSLog(@"*** zipArchiveDidUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", fileIndex, totalFiles, archivePath); + NSLog(@"*** zipArchiveDidUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", (int)fileIndex, (int)totalFiles, archivePath); +} + +- (void)zipArchiveProgressEvent:(NSInteger)loaded total:(NSInteger)total { + NSLog(@"*** zipArchiveProgressEvent: loaded: `%d` total: `%d`", (int)loaded, (int)total); + [progressEvents addObject:[[NSNumber alloc] initWithInteger:loaded]]; }