Description: This article describes multithreaded breakpoint downloads. The project uses the Apple-band class, which enables simultaneous opening of multiple threads to download a larger file. Because the implementation process is more complex, the complete code is posted below.
Realization: Download begins, create a file that is the same size as the file you want to download (if the file you want to download is 100M, create a 100M file in the sandbox, and then calculate the download amount for each segment, open multiple threads to download the data for each segment, and write the corresponding file section separately).
The main classes used in the project are as follows:
The completed implementation code is as follows:
Code in the primary controller:
#import "YYViewController.h"
#import "YYFileMultiDownloader.h"
@interface Yyviewcontroller ()
@ Property (Nonatomic, Strong) Yyfilemultidownloader *filemultidownloader;
@end
@implementation Yyviewcontroller
-(Yyfilemultidownloader *) Filemultidownloader
{
if (!_ Filemultidownloader) {
_filemultidownloader = [[Yyfilemultidownloader alloc] init];
Need to download the file remote URL
_filemultidownloader.url = @ "Http://192.168.1.200:8080/MJServer/resources/jre.zip";
Where to save the file
nsstring *caches = [Nssearchpathfordirectoriesindomains (nscachesdirectory, Nsuserdomainmask, YES) Lastobject];
NSString *filepath = [Caches stringbyappendingpathcomponent:@ "Jre.zip"];
_filemultidownloader.destpath = filepath;
}
return _filemultidownloader;
}
-(void) viewdidload
{
[super Viewdidload];
}
-(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
{
[self.filemultidownloader start];
}
@end
Customizing a base class
YYFileDownloader.h file
#import <Foundation/Foundation.h>
@interface yyfiledownloader:nsobject
{
BOOL _downloading;
}
/**
* required to download the file remote URL (connecting the server path)
/
@property (nonatomic, copy) NSString *url;
/**
* File storage path (file download to where) *
/@property (nonatomic, copy) NSString *destpath;
/**
* is downloading (there is no download, only the inside of the download to know) *
* * * *
@property (nonatomic, readonly, getter = isdownloading) BOOL Downloading;
/**
* Used to monitor download progress * *
@property (nonatomic, copy) void (^progresshandler) (double progress);
/**
* Start (Resume) Download
*
/(void) start;
/**
* Suspend download
/-(void) pause;
@end
YYFILEDOWNLOADER.M file
#import "YYFileDownloader.h" @implementation yyfiledownloader @end the download class inherits from Yyfiledownloader
YYFileSingDownloader.h file #import "YYFileDownloader.h" @interface where Yyfilesingledownloader:yyfiledownloader/** * started
*/@property (nonatomic, assign) long long begin;
/** * End of position * * * @property (nonatomic, assign) long long; @end yyfilesingdownloader.m file #import "YYFileSingleDownloader.h" @interface Yyfilesingledownloader () <
nsurlconnectiondatadelegate>/** * Connection object/@property (nonatomic, strong) nsurlconnection *conn;
/** * Write the data file handle * * * * @property (nonatomic, strong) Nsfilehandle *writehandle;
/** * The length of the current downloaded data is * * * @property (nonatomic, assign) long long currentlength; @end @implementation Yyfilesingledownloader-(Nsfilehandle *) Writehandle {if (!_writehandle) {_writehandle = [N
Sfilehandle FileHandleForWritingAtPath:self.destPath];
return _writehandle;
/** * Start (Restore) Download/-(void) Start {nsurl *url = [Nsurl URLWithString:self.url];
The default is GET request Nsmutableurlrequest *request = [Nsmutableurlrequest Requestwithurl:url];
Set Request header information NSString *value = [NSString stringwithformat:@ "Bytes=%lld-%lld", Self.begin + self.currentlength, self.end];
[Request Setvalue:value forhttpheaderfield:@ "Range"];
Self.conn = [nsurlconnection connectionwithrequest:request delegate:self];
_downloading = YES;
/** * Suspend Download * *-(void) Pause {[Self.conn cancel];
Self.conn = nil;
_downloading = NO; #pragma mark-nsurlconnectiondatadelegate Proxy Method/** * 1. When a response to the server is received (connected to the server), the */(void) connection is invoked: (nsurlconnection *) connection didreceiveresponse: (Nsurlresponse *) Response {}/** * 2. When the data received to the server is invoked (may be invoked multiple times, only partial data will be passed per invocation)/-(void) connection: (Nsurlconnection *) connection didreceivedata: (NSData *)
Data {//move to the tail of the file [Self.writehandle SeekToFileOffset:self.begin + self.currentlength];
Writes data from the currently moving position (end of file) [Self.writehandle Writedata:data];
Cumulative length Self.currentlength + = Data.length; Print Download Progress DoubLe progress = (double) self.currentlength/(Self.end-self.begin);
if (Self.progresshandler) {Self.progresshandler (progress); }/** * 3. When the server's data is accepted it will call the/-(void) connectiondidfinishloading: (nsurlconnection *) connection {//empty attribute value Self.currentlength =
0;
Close the connection (no more data is entered into the file) [Self.writehandle CloseFile];
Self.writehandle = nil; /** * Request error (failure) when called (Request timeout \ Disconnected network \ No network, generally refers to client error)/-(void) connection: (Nsurlconnection *) connection didfailwitherror: (nser
ROR *) Error {} @end
Design multi-threaded Downloader (use Hmfilemultidownloader to open multiple threads and download a file simultaneously)
A multithreaded downloader downloads only one file
YYFileMultiDownloader.h file
#import "YYFileDownloader.h"
@interface yyfilemultidownloader:yyfiledownloader
@end
YYFILEMULTIDOWNLOADER.M file
#import "YYFileMultiDownloader.h" #import "YYFileSingleDownloader.h" #define YYMAXDOWNLOADCOUNT 4 @interface Yyfilemul
Tidownloader () @property (nonatomic, strong) Nsmutablearray *singledownloaders;
@property (nonatomic, assign) long long totallength; @end @implementation Yyfilemultidownloader-(void) GetFileSize {nsmutableurlrequest *request = [Nsmutableurlrequest R
Equestwithurl:[nsurl URLWithString:self.url]]; Request.
HttpMethod = @ "Head";
Nsurlresponse *response = nil;
#warning here to use the asynchronous request [Nsurlconnection sendsynchronousrequest:request returningresponse:&response Error:nil];
Self.totallength = Response.expectedcontentlength;
}-(Nsmutablearray *) singledownloaders {if (!_singledownloaders) {_singledownloaders = [Nsmutablearray array];
Get file size [self getfilesize];
The download amount of each path is long long size = 0;
if (self.totallength% Yymaxdownloadcount = = 0) {size = Self.totallength/yymaxdownloadcount; else {size = SelF.totallength/yymaxdownloadcount + 1; }//Create n downloader for (int i = 0; i<yymaxdownloadcount; i++) {Yyfilesingledownloader *singledownloader =
[[Yyfilesingledownloader alloc] init];
Singledownloader.url = Self.url;
Singledownloader.destpath = Self.destpath;
Singledownloader.begin = i * size;
Singledownloader.end = Singledownloader.begin + size-1;
Singledownloader.progresshandler = ^ (double progress) {NSLog (@ "%d---%f", I, progress);
};
[_singledownloaders Addobject:singledownloader]; //Create a temporary file size with server file [[Nsfilemanager Defaultmanager] CreateFileAtPath:self.destPath contents:nil attribute
S:nil]; Let the length of the Self.destpath file be self.totallengt nsfilehandle *handle = [Nsfilehandle fileHandleForWritingAtPath:self.destPath
];
[Handle truncateFileAtOffset:self.totalLength];
return _singledownloaders; /** * Start (Restore) Download/-(void) Start {[Self.singledownloaders makeobjectsperformSelector: @selector (start)];
_downloading = YES;
/** * Suspend download/-(void) Pause {[Self.singledownloaders makeobjectsperformselector: @selector (pause)];
_downloading = NO;
} @end
Supplemental Note: How do I get the size of the file that will be downloaded?
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.