Add support for creating zip files
Basic zip files can be created (or appended to) by supplying the path to a zip file and either paths to existing files or NSData objects along with filenames.
This commit is contained in:
parent
ada9722309
commit
4fa1e0d060
@ -7,10 +7,25 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "minizip/zip.h"
|
||||
|
||||
@interface SSZipArchive : NSObject
|
||||
@interface SSZipArchive : NSObject {
|
||||
@private
|
||||
NSString *_path;
|
||||
zipFile _zip;
|
||||
}
|
||||
|
||||
// Unzip
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
|
||||
|
||||
// Zip
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
|
||||
|
||||
- (id)initWithPath:(NSString *)path;
|
||||
- (BOOL)open;
|
||||
- (BOOL)writeFile:(NSString *)path;
|
||||
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
|
||||
- (BOOL)close;
|
||||
|
||||
@end
|
||||
|
122
SSZipArchive.m
122
SSZipArchive.m
@ -148,6 +148,128 @@
|
||||
return success;
|
||||
}
|
||||
|
||||
#pragma mark - unzip
|
||||
|
||||
#define CHUNK 16384
|
||||
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths {
|
||||
|
||||
BOOL success = NO;
|
||||
|
||||
SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
|
||||
if ([zipArchive open]) {
|
||||
|
||||
for (NSString *path in paths) {
|
||||
[zipArchive writeFile:path];
|
||||
}
|
||||
|
||||
success = [zipArchive close];
|
||||
}
|
||||
[zipArchive release];
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString *)path
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_path = [path copy];
|
||||
// Initialization code here.
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_path release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)open {
|
||||
|
||||
NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
|
||||
|
||||
_zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
|
||||
|
||||
return (NULL != _zip);
|
||||
}
|
||||
|
||||
- (BOOL)writeFile:(NSString *)path {
|
||||
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);
|
||||
|
||||
void *buffer = malloc(CHUNK);
|
||||
unsigned int len = 0;
|
||||
|
||||
while (!feof(input)) {
|
||||
len = (unsigned int) fread(buffer, 1, CHUNK, input);
|
||||
zipWriteInFileInZip(_zip, buffer, len);
|
||||
}
|
||||
|
||||
zipCloseFileInZip(_zip);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename {
|
||||
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
|
||||
NSAssert((data != NULL), @"Nil data");
|
||||
|
||||
zipOpenNewFileInZip(_zip,
|
||||
[filename UTF8String],
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
Z_DEFLATED,
|
||||
Z_DEFAULT_COMPRESSION);
|
||||
|
||||
void *buffer = malloc(CHUNK);
|
||||
unsigned int offset = 0;
|
||||
NSUInteger length = [data length];
|
||||
unsigned int chunk_length;
|
||||
|
||||
while (offset < length) {
|
||||
chunk_length = MIN(CHUNK, ((unsigned int) length)-offset);
|
||||
[data getBytes:&buffer range:NSMakeRange(offset, chunk_length)];
|
||||
zipWriteInFileInZip(_zip, buffer, chunk_length);
|
||||
offset += chunk_length;
|
||||
}
|
||||
|
||||
zipCloseFileInZip(_zip);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)close {
|
||||
NSAssert((_zip != NULL), @"Attempting to close an archive which was never opened");
|
||||
|
||||
zipClose(_zip, NULL);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
|
@ -11,21 +11,32 @@
|
||||
|
||||
@interface SSZipArchiveTests ()
|
||||
- (NSString *)_cachesPath;
|
||||
- (NSString *)_createOutputPath;
|
||||
@end
|
||||
|
||||
@implementation SSZipArchiveTests
|
||||
|
||||
- (void)testBasicZipping {
|
||||
NSString *outputPath = [self _createOutputPath];
|
||||
|
||||
NSArray *inputPaths = [NSArray arrayWithObjects:
|
||||
[outputPath stringByAppendingPathComponent:@"Readme.markdown"],
|
||||
[outputPath stringByAppendingPathComponent:@"LICENSE"],
|
||||
nil];
|
||||
NSString *archivePath = [outputPath stringByAppendingPathComponent:@"CreatedArchive.zip"];
|
||||
[SSZipArchive createZipFileAtPath:archivePath withFilesAtPaths:inputPaths];
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
STAssertTrue([fileManager fileExistsAtPath:archivePath], @"Archive created");
|
||||
}
|
||||
|
||||
- (void)testBasicUnzipping {
|
||||
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
|
||||
NSString *outputPath = [[self _cachesPath] stringByAppendingPathComponent:@"basic"];
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if (![fileManager fileExistsAtPath:outputPath]) {
|
||||
[fileManager createDirectoryAtPath:outputPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
NSString *outputPath = [self _createOutputPath];
|
||||
|
||||
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *testPath = [outputPath stringByAppendingPathComponent:@"Readme.markdown"];
|
||||
STAssertTrue([fileManager fileExistsAtPath:testPath], @"Readme unzipped");
|
||||
|
||||
@ -40,6 +51,19 @@
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSString *)_createOutputPath {
|
||||
NSString *outputPath = [[self _cachesPath] stringByAppendingPathComponent:@"basic"];
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if (![fileManager fileExistsAtPath:outputPath]) {
|
||||
[fileManager createDirectoryAtPath:outputPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
// NSLog(@"outputPath: %@", outputPath);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
- (NSString *)_cachesPath {
|
||||
return [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
|
||||
stringByAppendingPathComponent:@"com.samsoffes.ssziparchive.tests"];
|
||||
|
Loading…
Reference in New Issue
Block a user