Objective-C: get image from gallery/camera and send via HTTP

unnamed

In this post we will get image from phone gallery and take photo from camera. The next task will be sending image to a backend.

Step 1.

Add 3 new values into Info.plist:

Screen Shot 2017-04-23 at 15.04.05

The first value is the string asking user a permission to use photo gallery. The second is for camera. The third to allow using HTTP (not HTTPS) server.

Step 2.

Draw interface.

UILabel *imageStatusLabel;
UIImageView *imageView;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self buildView];
}

- (void) buildView {
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    
    UIView *imageContainerView = [[UIView alloc] initWithFrame:CGRectMake(
                                                                          0,
                                                                          0,
                                                                          screenWidth,
                                                                          450)];
    imageContainerView.layer.borderColor = [UIColor grayColor].CGColor;
    imageContainerView.layer.borderWidth = 1.0f;
    [self.view addSubview:imageContainerView];
    
    CGFloat currentY = 30;
    
    imageStatusLabel = [[UILabel alloc] initWithFrame:CGRectMake(
                                                                30,
                                                                currentY,
                                                                imageContainerView.frame.size.width - 60,
                                                                20)];
    imageStatusLabel.text = @"No image";
    imageStatusLabel.textAlignment = NSTextAlignmentCenter;
    [imageContainerView addSubview:imageStatusLabel];
    currentY += imageStatusLabel.frame.size.height + 20;
    
    UIButton *selectImageButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                      (screenWidth - 200)/2,
                                                                      currentY,
                                                                      200,
                                                                      30)];
    [selectImageButton setTitle:@"Select image" forState:UIControlStateNormal];
    selectImageButton.showsTouchWhenHighlighted = true;
    selectImageButton.backgroundColor = [UIColor grayColor];
    [selectImageButton addTarget:self action:@selector(selectImage:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:selectImageButton];
    currentY += selectImageButton.frame.size.height + 20;
    
    UIButton *takePhotoButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                             (screenWidth - 200)/2,
                                                                             currentY,
                                                                             200,
                                                                             30)];
    [takePhotoButton setTitle:@"Take photo" forState:UIControlStateNormal];
    takePhotoButton.showsTouchWhenHighlighted = true;
    takePhotoButton.backgroundColor = [UIColor grayColor];
    [takePhotoButton addTarget:self action:@selector(takePhoto:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:takePhotoButton];
    currentY += takePhotoButton.frame.size.height + 20;

    
    imageView = [[UIImageView alloc] initWithFrame:CGRectMake(
                                                              30,
                                                              currentY,
                                                              imageContainerView.frame.size.width - 60,
                                                              200)];
    imageView.backgroundColor = [UIColor grayColor];
    [imageContainerView addSubview:imageView];
    currentY += imageView.frame.size.height + 20;
    
    UIButton *sendButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                      (screenWidth - 200)/2,
                                                                      currentY,
                                                                      200,
                                                                      30)];
    [sendButton setTitle:@"Send image" forState:UIControlStateNormal];
    sendButton.showsTouchWhenHighlighted = true;
    sendButton.backgroundColor = [UIColor grayColor];
    [sendButton addTarget:self action:@selector(sendImage:) forControlEvents:UIControlEventTouchUpInside];
    [imageContainerView addSubview:sendButton];
}

Initial view:

Screen Shot 2017-04-23 at 14.56.43

Step 3.

Code for taking image.

- (void) selectImage:(UIButton *) sender {
    NSLog(@"selectImage");
    UIImagePickerController *pickerViewController = [[UIImagePickerController alloc] init];
    pickerViewController.allowsEditing = YES;
    pickerViewController.delegate = self;
    [pickerViewController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
    [self presentViewController:pickerViewController animated:YES completion:nil];
}

- (void) takePhoto:(UIButton *) sender {
    NSLog(@"takePhoto");
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        UIImagePickerController *pickerViewController =[[UIImagePickerController alloc]init];
        pickerViewController.allowsEditing = YES;
        pickerViewController.delegate = self;
        pickerViewController.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self presentViewController:pickerViewController animated:YES completion:nil];
    } else {
        UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Error" message:@"Camera is not available" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
        [alert addAction:defaultAction];
        [self presentViewController:alert animated:YES completion:nil];
    }
}

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [self dismissViewControllerAnimated:picker completion:nil];
    UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
    imageView.image = image;
    imageStatusLabel.text = @"Image imported into the app";
}

selectImage – get image from phone gallery. takePhoto – get image from camera. Taking photo will not work in simulator and alert will be shown. Logic of selectImage and takePhoto is common: call UIImagePickerController and get image when user finish picking. We need implement two delegates:

@interface ViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

Example:

unnamed

Step 4.

Sending image via HTTP using POST. I added image data into HTTP body. We can also send image data in POST field.

- (void) sendImage:(UIButton *) sender {
    NSLog(@"sendImage");
    
    imageStatusLabel.text = @"Image is uploading";
    
    UIImage *yourImage= imageView.image;
    NSData *imageData = UIImagePNGRepresentation(yourImage);
    NSString *postLength = [NSString stringWithFormat:@"%d", (int)[imageData length]];
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setHTTPMethod:@"POST"];
    [request setURL:[NSURL URLWithString:@"http://{SERVER_ADDRESS}/upload.php"]];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:imageData];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {
                                      if (data == nil) {
                                          [self printCannotLoad];
                                      } else {
                                          [self printSuccess];
                                      }
                                  }];
    [task resume];
}

- (void) printCannotLoad {
    dispatch_sync(dispatch_get_main_queue(), ^{
        imageStatusLabel.text = @"Cannot upload";
    });
}

- (void) printSuccess {
    dispatch_sync(dispatch_get_main_queue(), ^{
        imageStatusLabel.text = @"Successfully uploaded";
    });
}

Step 5.

You can see that we are sending image to address http://{SERVER_ADDRESS}/upload.php . For testing purposes you can place this one line of code in upload.php:

<?php file_put_contents("image.png", file_get_contents("php://input")); ?>

Step 6.

Test on simulator and real device.

Screen Shot 2017-04-23 at 14.55.09

Project on GitHub.

 

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Profile photo of Doszhan Kalibek

Doszhan Kalibek