Make writing a habit together! This is the sixth day of my participation in the “Gold Digging Day New Plan ยท April More text Challenge”. Click here for more details.

The introduction

NSData + (id)dataWithContentsOfURL (NSURL *) URL; Send an HTTP request to download using NSURLConnection.

If you are downloading images, you can also use the SDWebImage framework

I HTTP Range (specifies the size of each packet downloaded from the network)

By setting the request header Range, you can specify the size of each packet downloaded from the network, which can be used for breakpoint download


 [request setValue:[NSString stringWithFormat:@"bytes=%lld-".self.currentDataLength] forHTTPHeaderField:@"Range"];
Copy the code

1.1 the Range of the sample

Bytes =0-499 First 500 bytes from 0 to 499 bytes=500-999 Second 500 bytes from 500 to 999 bytes=500- All bytes from 500 bytes bytes=-500 Last 500 bytes Bytes =500-599,800-899 Specify several ranges simultaneouslyCopy the code

1.2 the Range summary

  • Used to separate

The preceding number indicates the start number of bytes and the array indicates the end number of bytes, not the end number for grouping. Multiple ranges can be specified at once, though rarely

  • Third party decompression framework – SSZipArchive

Adding to your project

Add SSZipArchive. H, SSZipArchive. M, and minizip to your projectCopy the code
  • Usage

// Unzipping
NSString *zipPath = @"path_to_your_zip_file";
NSString *destinationPath = @"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:zipPath toDestination:destinationPath];
 
// Zipping
NSString *zippedPath = @"path_where_you_want_the_file_created";
NSArray *inputPaths = [NSArray arrayWithObjects:
                       [[NSBundle mainBundle] pathForResource:@"photo1" ofType:@"jpg"],
                       [[NSBundle mainBundle] pathForResource:@"photo2" ofType:@"jpg"]
                       nil];
[SSZipArchive createZipFileAtPath:zippedPath withFilesAtPaths:inputPaths];
Copy the code

1.3 NSURLConnection breakpoint download


  • Breakpoint downloading

#pragmaMark - Breakpoint download
- (IBAction)pause:(UIButton *)sender {
    [sender setSelected:!sender.selected];
    if (sender.selected) {// Continue downloading
        NSURL *url = [NSURL URLWithString:@ "http://127.0.0.1:8080/MJServer/resources/videos/iPhoneSimulator6.1.sdk.zip"];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        / / set the Range
        [request setValue:[NSString stringWithFormat:@"bytes=%lld-".self.currentDataLength] forHTTPHeaderField:@"Range"];
        NSLog(@ "% @"[NSString stringWithFormat:@"bytes=%lld-".self.currentDataLength]);
        self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
 
    }else{// Pause the download
        [self.connection cancel];
        self.connection = nil; }}#pragma mark - NSURLConnectionDataDelegate
 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    self.response = (NSHTTPURLResponse*)response;
    if (self.currentDataLength) {// A new request after the breakpoint, no need to execute the following code
        return;
    }
    // Create a file with the same size as the expected download file into the sandbox. ---- Single-thread breakpoint download simply creates an empty file
    NSString *filePath = HSCachePath([connection.currentRequest.URL lastPathComponent]);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager createFileAtPath:filePath contents:nil attributes:nil];
    // Create the file handle
    self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
    self.totalDataLength = response.expectedContentLength;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    self.currentDataLength += data.length;
// NSDictionary *dict = [self.response allHeaderFields];
// NSString *length = dict[@"Content-Length"]; // Get the desired length
// NSString *length = self.response.expectedContentLength;
        [self.circularProgressView setProgress:self.currentDataLength*1.0/self.totalDataLength];
    [self.fileHandle seekToEndOfFile];
    [self.fileHandle writeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    [self.fileHandle closeFile];
    self.currentDataLength =0;
 
}
Copy the code

II File Upload (Multipart /form-data)


  • Set the key value of the Post header.
/*Content-Type multipart/form-data; Boundary = Mark string (cannot be In Chinese)*/
[request setValue:@"multipart/form-data; boundary=hisun" forHTTPHeaderField:@"Content-Type"];
Copy the code

The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types

2.1 File Upload Request Body


  • File parameters

Content-disposition: form-data; content-disposition: content-disposition: form-data; Name =” parameter name “; Filename =” filename “content-type: MIMEType specifies the file Type

  • Non-file parameter

Content-disposition: form-data; content-disposition: content-disposition: form-data; Name =” parameter name “; Parameter values — boundary — (end tag)

Closing tag (– boundary –)

  • Zip folder
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
   NSString *filePath = [cachePath stringByAppendingPathComponent:@"images"];
   NSString *zipPath = [cachePath stringByAppendingPathComponent:@"images.zip"];
   NSLog(@"%@,%@",filePath,zipPath);
   [SSZipArchive createZipFileAtPath:zipPath withContentsOfDirectory:filePath];
Copy the code
  • Get the mimeType based on the URL
- (NSString *) mimeTypeWithUrl:(NSURL *)url{
    NSURLResponse *response;
    [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:&response error:nil];
    return response.MIMEType;
}
 
//    NSString *mimetype = [self mimeTypeWithUrl:[NSURL fileURLWithPath:@"/Users/devzkn/Desktop/minion_02.png"]];
Copy the code

2.2 Uploading files using NSMutableURLRequest


#define HSBasicUrl  @"http://127.0.0.1:8080/KNServer/"
 
#define HSUrl(name) [NSURL URLWithString:[NSString stringWithFormat:@"% @ % @",HSBasicUrl,name]]
 
#define HSFileBoundary @"hisun"
 
#define HSFileEndedBounary [NSString stringWithFormat:@"-- % @ -",HSFileBoundary]
 
#define HSFileStartBoundary [NSString stringWithFormat:@"-- % @",HSFileBoundary]
 
#define HSNewLine @"\r\n"
 
#define HSStringEncoding(str) [str dataUsingEncoding:NSUTF8StringEncoding]
#pragmaMark - File upload
 
- (void)upload:(NSString*)fileName mimeType:(NSString *)mimeType fileData:(NSData*)fileData params:(NSDictionary*)params{
 
    // Set the request body
 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:HSUrl(@"upload")];
 
    // Prepare the request body data
 
    NSMutableData *data =[NSMutableData data];
 
    / * request body: 1) - the upload file parameters marked string (border) Content - Disposition: the form - data; Name =" parameter name "; Filename =" filename "content-type: MIMEType 2) Non-file parameter -- Content-disposition: form-data; Name =" Parameter name "Parameter value 3) boundary - (end tag) */
 
    [data appendData:HSStringEncoding(HSFileStartBoundary)];/ / line
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
    NSString *disposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"".@"file",fileName];
 
    [data appendData:HSStringEncoding(disposition)];/ / parameter name
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
    NSString *mimeTypeStr = [NSString stringWithFormat:@"Content-Type:%@",mimeType];
 
    [data appendData:HSStringEncoding(mimeTypeStr)];
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
     
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
    [data appendData:fileData];
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
    // Set non-file data
 
    [params enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
 
        [data appendData:HSStringEncoding(HSFileStartBoundary)];/ / line
 
        [data appendData:HSStringEncoding(HSNewLine)];
 
         
 
        NSString *disposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"",key];
 
        [data appendData:HSStringEncoding(disposition)];/ / parameter name
 
        [data appendData:HSStringEncoding(HSNewLine)];
 
         
 
         
 
        [data appendData:HSStringEncoding(HSNewLine)];
 
        [data appendData:HSStringEncoding([obj description])];
 
        [data appendData:HSStringEncoding(HSNewLine)];
 
    }];
 
    / / the end
 
    [data appendData:HSStringEncoding(HSFileEndedBounary)];
 
    [data appendData:HSStringEncoding(HSNewLine)];
 
    [request setHTTPBody:data];
 
    [request setHTTPMethod:@"post"];
 
    [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",HSFileBoundary] forHTTPHeaderField:@"Content-Type"];
 
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
 
        NSLog(@ % @, % @ "",response,[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]);
 
    }];
 
     
}
Copy the code

2.3 NSURLSession- Resumable Breakpoint



- (NSURLSession *)session{
    if (_session == nil) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue] ];
    }
    return _session;
}
#pragmaMark - Breakpoint download
- (IBAction)pause:(UIButton *)sender {
    [sender setSelected:!sender.selected];
    if (sender.selected) {
        if (self.task == nil) {
            if (self.resumeData) {
                [self resumeDownLoad];// Continue downloading
            }else{[self startSessionWithConfiguration];// Start downloading}}}else{[self pauseDownload];/ / pause}}#pragmaMark - NSURLSessionDownloadDelegate view the download progress
- (void) startSessionWithConfiguration{
    NSLog(@"%s----start ",__func__);
    [self.circularProgressView setProgress:0];
    [self.button setSelected:YES];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:HSURL(@ "resources/videos/iPhoneSimulator6.1. SDK. Zip")];
    self.task = [self.session downloadTaskWithRequest:request];
    [self.task resume];// Execute the task
 
}
- (void)resumeDownLoad{
    if (self.resumeData == nil) {
        return;
    }
    NSLog(@ % s -- -- -- -- -- "continue",__func__);
    self.task = [self.session downloadTaskWithResumeData:self.resumeData];
    [self.task resume];
    self.resumeData = nil;
 
}
- (void)pauseDownload {
    NSLog(@ % s "-- -- -- -- -- - suspended",__func__);
    if (self.task == nil) {
        return;
    }
    /* A completion handler that is called when the download has been successfully canceled. If the download is resumable, The Completion handler is provided with a resumeData object. Your app can later pass this object to a session's downloadTaskWithResumeData: or downloadTaskWithResumeData:completionHandler: method to create a new task that resumes the download where it left off. This contains the URL to create the link and the connection header information (Range) */
    HSweakself(weakself);
    [self.task  cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        weakself.resumeData = resumeData;
        weakself.task = nil;
    }];
}
 
/* Sent when a download task that has completed a download. The delegate should * copy or move the file at the given location to a new location as it will be * removed when the delegate message returns. URLSession:task:didCompleteWithError: will * still be called. */
 
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
    NSString *filePath = HSCachePath(downloadTask.response.suggestedFilename);
    NSLog(@"%s----%@ --%@ --%@",__func__,downloadTask.response,filePath,location.path);
    // Move location file to filePath
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager moveItemAtPath:location.path toPath:filePath error:nil];
     
 
}
/* Sent periodically to notify the delegate of download progress. */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    NSLog(@"%s----%@,bytesWritten:%lld,------totalBytesWritten:%lld,------totalBytesExpectedToWrite:%lld------%f%%",__func__,downloadTask,bytesWritten,totalBytesWritten,totalBytesExpectedToWrite,(double)totalBytesWritten*100.0/totalBytesExpectedToWrite);
    [self.circularProgressView setProgress:(double)totalBytesWritten*1.0/totalBytesExpectedToWrite];
     
 
}
 
/* Sent when a download has been resumed. If a download failed with an * error, the -userInfo dictionary of the error will contain an * NSURLSessionDownloadTaskResumeData key, whose value is the resume * data. */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
    NSLog(@"%s-----fileOffset:%lld,---expectedTotalBytes:%lld",__func__,fileOffset,expectedTotalBytes);
}
Copy the code

see also

๐Ÿ… Contact author: iOS Reverse (public number: iosrev)


๐Ÿ… Author profile: CSDN blog expert certification ๐Ÿ† international Top 50, Huawei Cloud enjoy expert certification ๐Ÿ†, iOS reverse public number master


๐Ÿ… Resume template, technical assistance. Pay attention to me, all for you.