-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathZipFileDownloader.m
140 lines (118 loc) · 4.87 KB
/
ZipFileDownloader.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//
// ZipFileDownloader.m
// CoughDrop
//
// Created by Joshua Dutton on 2/4/16.
//
//
#import "ZipFileDownloader.h"
#import "SSZipArchive.h"
@interface ZipFileDownloader() <NSURLSessionDelegate, NSURLSessionDataDelegate>
@property NSURLSession *session;
@property NSURLSessionDownloadTask *downloadTask;
@property NSURL *unZipURL;
@property (nonatomic, copy) void (^progressBlock)(double progress, BOOL isCompleted);
@property (nonatomic, copy) void (^errorBlock)(NSString *errorMessage);
@end
const double DownloadPercentageWeight = 0.75;
@implementation ZipFileDownloader
- (instancetype)init
{
self = [super init];
if (self) {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
}
return self;
}
- (void)downloadfileAtURL:(NSURL *)voiceURL
andUnZipToURL:(NSURL *)unZipURL
progressBlock:(void (^)(double, BOOL))progressBlock
errorBlock:(void (^)(NSString *))errorBlock
{
self.unZipURL = unZipURL;
self.progressBlock = progressBlock;
self.errorBlock = errorBlock;
self.isDownloading = true;
// Download progress is updated in the NSURLSessionDataDelegate methods
self.downloadTask = [self.session downloadTaskWithURL:voiceURL];
[self.downloadTask resume];
}
#pragma mark - NSURLSessionDelegate and NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
if (self.errorBlock) {
self.errorBlock(@"unable to download file");
}
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
if (downloadTask == self.downloadTask) {
[self updateProgressForDownloadWithAmountWritten:fileOffset total:expectedTotalBytes];
}
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (downloadTask == self.downloadTask) {
[self updateProgressForDownloadWithAmountWritten:totalBytesWritten total:totalBytesExpectedToWrite];
}
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
if (downloadTask == self.downloadTask) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *zipFileURL = [self.unZipURL URLByAppendingPathComponent:@"toUnzip.zip"];
NSError *error;
[fileManager removeItemAtURL:zipFileURL error:&error];
BOOL success = [fileManager moveItemAtURL:location toURL:zipFileURL error:&error];
if (success) {
[self unZipFileAtURL:zipFileURL];
} else if (self.errorBlock) {
self.errorBlock(@"unable to unzip file");
}
}
}
#pragma mark - Download and UnZip helpers
- (void)unZipFileAtURL:(NSURL *)tempFileURL
{
[SSZipArchive unzipFileAtPath:tempFileURL.path
toDestination:self.unZipURL.path
progressHandler:^(NSString *entry, unz_file_info zipInfo, long entryNumber, long total) {
[self updateProgressForUnZipWithAmountWritten:entryNumber total:total];
}
completionHandler:^(NSString *path, BOOL succeeded, NSError *error) {
if (succeeded && self.progressBlock) {
self.progressBlock(1.0, YES);
} else if (self.errorBlock){
self.errorBlock(@"unable to unzip file");
}
// cleanup
[[NSFileManager defaultManager] removeItemAtURL:tempFileURL error:nil];
self.isDownloading = NO;
self.downloadTask = nil;
self.progressBlock = nil;
self.errorBlock = nil;
}];
}
- (void)updateProgressForDownloadWithAmountWritten:(double)written total:(double)total
{
double percent = written/total * DownloadPercentageWeight;
[self updateProgressWithPercent:percent];
}
- (void)updateProgressForUnZipWithAmountWritten:(double)written total:(double)total
{
const double unZipPercentageWeight = 1.0 - DownloadPercentageWeight;
double percent = DownloadPercentageWeight + (written/total * unZipPercentageWeight);
[self updateProgressWithPercent:percent];
}
- (void)updateProgressWithPercent:(double)percent
{
double trimmedPercent = round(percent * 100.0) / 100.0;
if (trimmedPercent >= 1.0) {
return;
}
if (self.progressBlock) {
self.progressBlock(trimmedPercent, NO);
}
}
@end