From 7aea62f0dd91e1c612367f6b8f4ec65d5987bdaf Mon Sep 17 00:00:00 2001 From: Ingmar Date: Sat, 9 Mar 2013 05:36:20 -0800 Subject: [PATCH] - add folder zipping functionality - fixed zipping test case [testZipping] (zipped an empty archive) --- SSZipArchive.h | 1 + SSZipArchive.m | 63 +++++++++++++++++++++++++++++++++------ Tests/SSZipArchiveTests.m | 21 +++++++++++-- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/SSZipArchive.h b/SSZipArchive.h index 7435fb1..13a539f 100644 --- a/SSZipArchive.h +++ b/SSZipArchive.h @@ -25,6 +25,7 @@ // Zip + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames; ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath; - (id)initWithPath:(NSString *)path; - (BOOL)open; diff --git a/SSZipArchive.m b/SSZipArchive.m index baf0be3..f07d37d 100644 --- a/SSZipArchive.m +++ b/SSZipArchive.m @@ -293,6 +293,35 @@ } ++ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath { + BOOL success = NO; + SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path]; + + if ([zipArchive open]) { + // use a local filemanager (queue/thread compatibility) + NSFileManager *fileManager = [[NSFileManager alloc] init]; + NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:directoryPath]; + + NSString *fileName; + while (fileName = [dirEnumerator nextObject]) { + BOOL isDir; + NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName]; + [fileManager fileExistsAtPath:fullFilePath isDirectory:&isDir]; + if (!isDir) { + [zipArchive writeFileAtPath:fullFilePath withFileName:fileName]; + } + } + success = [zipArchive close]; + } + +#if !__has_feature(objc_arc) + [zipArchive release]; +#endif + + return success; +} + + - (id)initWithPath:(NSString *)path { if ((self = [super init])) { _path = [path copy]; @@ -329,27 +358,43 @@ } -- (BOOL)writeFile:(NSString *)path { - NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened"); +- (BOOL)writeFile:(NSString *)path +{ + return [self writeFileAtPath:path withFileName:nil]; +} +// supports writing files with logical folder/directory structure +// *path* is the absolute path of the file that will be compressed +// *fileName* is the relative name of the file how it is stored within the zip e.g. /folder/subfolder/text1.txt +- (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName { + NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened"); + FILE *input = fopen([path UTF8String], "r"); if (NULL == input) { return NO; } - - zipOpenNewFileInZip(_zip, [[path lastPathComponent] UTF8String], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, - Z_DEFAULT_COMPRESSION); - + + const char *afileName; + if (!fileName) { + afileName = [path.lastPathComponent UTF8String]; + } + else { + afileName = [fileName UTF8String]; + } + + zipOpenNewFileInZip(_zip, afileName, NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + void *buffer = malloc(CHUNK); unsigned int len = 0; - while (!feof(input)) { + + while (!feof(input)) + { len = (unsigned int) fread(buffer, 1, CHUNK, input); zipWriteInFileInZip(_zip, buffer, len); } - + zipCloseFileInZip(_zip); free(buffer); - fclose(input); return YES; } diff --git a/Tests/SSZipArchiveTests.m b/Tests/SSZipArchiveTests.m index bc45c64..fdeb2b5 100644 --- a/Tests/SSZipArchiveTests.m +++ b/Tests/SSZipArchiveTests.m @@ -26,11 +26,15 @@ - (void)testZipping { - NSString *outputPath = [self _cachesPath:@"Zipped"]; + // use extracted files from [-testUnzipping] + NSString *inputPath = [self _cachesPath:@"Regular"]; NSArray *inputPaths = [NSArray arrayWithObjects: - [outputPath stringByAppendingPathComponent:@"Readme.markdown"], - [outputPath stringByAppendingPathComponent:@"LICENSE"], + [inputPath stringByAppendingPathComponent:@"Readme.markdown"], + [inputPath stringByAppendingPathComponent:@"LICENSE"], nil]; + + NSString *outputPath = [self _cachesPath:@"Zipped"]; + NSString *archivePath = [outputPath stringByAppendingPathComponent:@"CreatedArchive.zip"]; [SSZipArchive createZipFileAtPath:archivePath withFilesAtPaths:inputPaths]; @@ -38,6 +42,17 @@ STAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:archivePath], @"Archive created"); } +- (void)testDirectoryZipping { + // use Unicode as folder (has a file in root and a file in subfolder) + NSString *inputPath = [self _cachesPath:@"Unicode"]; + + NSString *outputPath = [self _cachesPath:@"FolderZipped"]; + NSString *archivePath = [outputPath stringByAppendingPathComponent:@"ArchiveWithFolders.zip"]; + + [SSZipArchive createZipFileAtPath:archivePath withContentsOfDirectory:inputPath]; + STAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:archivePath], @"Folder Archive created"); +} + - (void)testUnzipping { NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];