iOS NSURLSession Get, Post, Upload, Download Example

From article iOS NSURLSession Tutorial you have learnt how to create NSURLSession and related tasks to implement related network task such as send request, download file, upload file etc. This article will show you some examples about those url session tasks.

1. Use NSURLSessionDataTask To Implement Get Or Post Request.

1.1 Implement Post Request.

// Create NSURLSession object.
NSURLSession *session = [NSURLSession sharedSession];

// Create a NSURL object.
NSURL *url = [NSURL URLWithString:@"http://www.yahoo.com/regist"];

// Create post request object with the url.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Set request method to POST.
request.HTTPMethod = @"POST";
// Set post username and password data.
request.HTTPBody = [@"username=Richard&pwd=888888" dataUsingEncoding:NSUTF8StringEncoding];

// Create the NSURLSessionDataTask post task object.
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        
        // Print out the result JSON format data. 
        NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);

        }];

// Execute the task
[task resume];

1.2 Implement Get Request.

// Create NSURLSession object
NSURLSession *session = [NSURLSession sharedSession];

// Create a NSURL object.
NSURL *url = [NSURL URLWithString:@"http://www.yahoo.com/download.cgi?id=1"];

// Create NSURLSessionDataTask task object by url and session object.
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    
    // Print response JSON data in the console.
    NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);

}];

// Begin task.
[task resume];

2. Use NSURLSessionUploadTask To Upload File.

There are two ways to upload files using NSURLSessionUploadTask.

2.1 Upload Data.

[self.session uploadTaskWithRequest:request
        fromData:body
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"-------%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
        }];

2.2 Upload File.

NSURLSessionUploadTask *task =
[[NSURLSession sharedSession] uploadTaskWithRequest:request
fromFile:fileName
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}]

2.3 Upload Data Stream Example.

The advantage of this approach is that the upload data size is unlimited.

- (void) NSURLSessionUploadFileDataTaskTest {
        // Create upload url string.
        NSString *urlString = @"http://www.yahoo.com/upload.cgi";

        // Create upload NSURL object.
        NSURL *url = [NSURL URLWithString:urlString];

        // Create request object.
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        // Request Use POST method.
        request.HTTPMethod = @"POST";

        // Create NSURLSession object.
        NSURLSession *session = [NSURLSession sharedSession];

        // Create a NSURLSessionUploadTask object to Upload data for a jpg image.
        NSURLSessionUploadTask *task =[session uploadTaskWithRequest:request fromData:[NSData dataWithContentsOfFile:@"/Users/Desktop/abc.jpg"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

            if (error == nil) {
                // Upload success.
                NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
            } else {
                // Upload fail.
                NSLog(@"upload error:%@",error);
            }

        }];

        // Start the task.
        [task  resume];
}

2.4 Upload Multiple Form Elements Together.

The key to uploading form is to concat multiple form elements as request body part.

Method NSURLSessionUploadFormTaskTest.

- (void)NSURLSessionUploadFormTaskTest {
        // Create a url string from localhost web server.
        NSString *urlString = @"http://localhost/upload/upload.php";
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
        // Create NSURL object.
        NSURL *url = [NSURL URLWithString:urlString];

        // Create request with the url.
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        // Set POST method to the request.
        request.HTTPMethod = @"POST";

        // Specify the content type string for form data.
        NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",@"boundary"];

        // Set request Content-Type header value.
        [request setValue:contentType forHTTPHeaderField:@"Content-Type"];
        
        // Get form data from local image path.
        NSData* data = [self getHttpBodyWithFilePath:@"/Users/Desktop/abc.jpg" formName:@"file" reName:@"abc_1.jpg"];
        request.HTTPBody = data;
        // Set Content-Length http header.
        [request setValue:[NSString stringWithFormat:@"%lu",data.length] forHTTPHeaderField:@"Content-Length"];

        // Use dataTask
        NSURLSession *session = [NSURLSession sharedSession];
        [[ session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
        NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
        NSLog(@"upload error:%@",error);
        }

        }] resume];
        #if 0
        // Use uploadTask to start upload.
        NSURLSession *session = [NSURLSession sharedSession];
        [[session uploadTaskWithRequest:request fromData:nil     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
        NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
        NSLog(@"upload error:%@",error);
        }
        }] resume];
        #endif
}

The form splicing format is as follows, boundary is the dividing line.

--boundary-- 
Content-Disposition:form-data;name=”form name”;filename=”upload file name”
Content-Type:Upload file MIME Types
Binary data of upload file;
--boundary--

Method getHttpBodyWithFilePath

/// filePath: Local upload file path, formName:form name, newName:server side file name after upload.
- (NSData *)getHttpBodyWithFilePath:(NSString *)filePath formName:(NSString *)formName newName:(NSString *)newName
  {
        NSMutableData *data = [NSMutableData data];
        NSURLResponse *response = [self getLocalFileResponse:filePath];
        // response contains file content type:MIMEType, file content length:expectedContentLength, file name:suggestedFilename
        NSString *fileType = response.MIMEType;

        // If the uploaded file name is not passed in, use the local file name!
        if (newName == nil) {
        newName = response.suggestedFilename;
        }

        // Form splicing.
        NSMutableString *headerStrM =[NSMutableString string];
        [headerStrM appendFormat:@"--%@\r\n",@"boundary"];
        // name:Form name  filename:Upload file name.
        [headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",formName,newName];
        [headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",fileType];
        [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]];

        // Get file content data.
        NSData *fileData = [NSData dataWithContentsOfFile:filePath];
        [data appendData:fileData];

        NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",@"boundary"];
        [data appendData:[footerStrM  dataUsingEncoding:NSUTF8StringEncoding]];
        
        return data;
 }

Method getLocalFileResponse

 /// Get response object, contains file type and file name.
 - (NSURLResponse *)getLocalFileResponse:(NSString *)urlString
    {
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
        // Create local file request url.
        NSURL *url = [NSURL fileURLWithPath:urlString];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        __block NSURLResponse *localResponse = nil;
        // NSURLSession synchronous requests are implemented using semaphore
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        localResponse = response;
        dispatch_semaphore_signal(semaphore);
        }] resume];
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        return  localResponse;
 }

3. Use NSURLSessionDownloadTask To Implement Download File Task.

- (void)NSURLSessionDownloadTaskTest {
        // Create download file url
        NSString *urlString = [NSString stringWithFormat:@"http://www.yahoo.com/logo.jpg"];
        // Encoding special charactor.
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        NSURL *url = [NSURL URLWithString:urlString];

        // Create request.
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        // Create shared NSURLSession object.
        NSURLSession *sharedSession = [NSURLSession sharedSession];

        // Create download task
        NSURLSessionDownloadTask *downloadTask = [sharedSession downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
        // location: Download file save directory after download task complete, the download file is saved in the TMP folder by default.
        // It will only be saved temporarily, so it needs to be stored separately.
        NSLog(@"location:%@",location.path);

        // Test download task in emulator to facilitate downloading to the Mac desktop.
        // NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filePath = @"/Users/Desktop/logo.jpg";
        NSError *fileError;
        [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError];
        if (fileError == nil) {
            NSLog(@"file download and save success");
        } else {
            NSLog(@"file save error: %@",fileError);
        }
        } else {
            NSLog(@"download error:%@",error);
        }
        }];

        // Start download task.
        [downloadTask resume];
}