Large file download
Plan 1:Utilize NSURLConnection and its proxy method, and NSFileHandle (not recommended after iOS9)
Related variables:
@property (nonatomic,strong) NSFileHandle *writeHandle; @property (nonatomic,assign) long long totalLength;
1>Send a request
// Create a request NSURL *url = [NSURL URLWithString:@""]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; // Use NSURLConnection to initiate an asynchronous request [NSURLConnection connectionWithRequest:request delegate:self];
2> Process the data returned by the server in the proxy method
/** Call the following proxy method when receiving the server's response 1. Create an empty file 2. Use a handle object to associate this empty file with the purpose of making it easier to write data behind an empty file */ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response { // Create file path NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject]; NSString *filePath = [caches stringByAppendingPathComponent:@""]; // Create an empty file into the sandbox NSFileManager *mgr = [NSFileManager defaultManager]; [mgr createFileAtPath:filePath contents:nil attributes:nil]; // Create a file handle for writing data = [NSFileHandle fileHandleForWritingAtPath:filePath]; // Get the total size of the file = ; } /** Call the following proxy method when receiving file data returned by the server Use the handle object to add data to the end of the file */ - (void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data { // Move to the end of the file [ seekToEndOfFile]; // Write data to the sandbox [ writeData:data]; } /** Close the handle object when all data is received */ - (void)connectionDidFinishLoading:(NSURLConnection *)connection { // Close the file and clear it [ closeFile]; = nil; }
Plan 2:NSURLSessionDownloadTask and NSFileManager using NSURLSession
NSURLSession *session = [NSURLSession sharedSession]; NSURL *url = [NSURL URLWithString:@""]; // Can be used to download large files, and the data will be stored in the tmp folder in the sandbox NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { // location: the path to store temporary files (downloaded files) // Create storage file path NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject]; //: The file name recommended is generally the same as the file name on the server side NSString *file = [caches stringByAppendingPathComponent:]; /**Cut or copy temporary files to the Caches folder AtPath: file path before clipping toPath: the file path after clipping */ NSFileManager *mgr = [NSFileManager defaultManager]; [mgr moveItemAtPath: toPath:file error:nil]; }]; [task resume];
Plan 3:Proxy method and NSFileManger using NSURLSessionDownloadDelegate
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // Create a download task and set up a proxy NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURL *url = [NSURL URLWithString:@""]; NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url]; [task resume]; } #pragma mark - /** Called after downloading Parameters: lication The path of the temporary file (downloaded file) */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ // Create storage file path NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject]; //: The file name recommended is generally the same as the file name on the server side NSString *file = [caches stringByAppendingPathComponent:]; /**Cut or copy temporary files to the Caches folder AtPath: file path before clipping toPath: the file path after clipping */ NSFileManager *mgr = [NSFileManager defaultManager]; [mgr moveItemAtPath: toPath:file error:nil]; } /** It will be called whenever a part is downloaded (may be called multiple times) parameter: bytesWritten How many downloads did this call totalBytesWritten How long has the accumulated written into the sandbox? totalBytesExpectedToWrite file size */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ // Here you can do some operations such as displaying progress} /** Used when restoring download */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { // Used for breakpoint continuous transmission}
Breakpoint download
Plan 1:
1>Add two new variables and buttons on the basis of plan one
@property (nonatomic,assign) long long currentLength; @property (nonatomic,strong) NSURLConnection *conn;
2> Add the following code to the proxy method that receives the data returned by the server
// Record breakpoints and accumulate file length += ;
3> Click the button to start (continue) or pause download
- (IBAction)download:(UIButton *)sender { = !; if () { // Continue (start) download NSURL *url = [NSURL URLWithString:@""]; // ****The key point is to use NSMutableURLRequest to set the request header Range NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url]; NSString *range = [NSString stringWithFormat:@"bytes=%lld-",]; [mRequest setValue:range forHTTPHeaderField:@"Range"]; // download = [NSURLConnection connectionWithRequest:mRequest delegate:self]; }else{ [ cancel]; = nil; } }
4> Add the following code in the first line of the proxy method that receives the server response execution to prevent repeated creation of empty files
if () return;
Plan 2:Proxy method using NSURLSessionDownloadDelegate
Required variables
@property (nonatomic,strong) NSURLSession *session; @property (nonatomic,strong) NSData *resumeData; //Includes the start location of the continued download and the downloaded URL@property (nonatomic,strong) NSURLSessionDownloadTask *task;
method
// Lazy loading session- (NSURLSession *)session { if (!_session) { NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]; } return _session; } - (IBAction)download:(UIButton *)sender { = !; if ( == nil) { // Start (continue) Download if () { // Recover the data originally [self resume]; }else{ [self start]; // Start without data } }else{ // pause [self pause]; } } // Start from scratch- (void)start{ NSURL *url = [NSURL URLWithString:@""]; = [ downloadTaskWithURL:url]; [ resume]; } // pause- (void)pause{ __weak typeof(self) vc = self; [ cancelByProducingResumeData:^(NSData * _Nullable resumeData) { //resumeData: contains the start location for continuing to download and the downloaded URL = resumeData; = nil; }]; } // recover- (void)resume{ // Pass in the data returned from the last pause of download and reply to the download = [ downloadTaskWithResumeData:]; // Start the task [ resume]; // Clear = nil; } #pragma mark - NSURLSessionDownloadDelegate /** Called after downloading Parameters: lication The path of the temporary file (downloaded file) */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ // Create storage file path NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject]; //: The file name recommended is generally the same as the file name on the server side NSString *file = [caches stringByAppendingPathComponent:]; /**Cut or copy temporary files to the Caches folder AtPath: file path before clipping toPath: the file path after clipping */ NSFileManager *mgr = [NSFileManager defaultManager]; [mgr moveItemAtPath: toPath:file error:nil]; } /** It will be called whenever a part is downloaded (may be called multiple times) parameter: bytesWritten How many downloads did this call totalBytesWritten How long has the accumulated written into the sandbox? totalBytesExpectedToWrite file size */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ // Here you can do some operations such as displaying progress} /** Used when restoring download */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { }
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.