Base64 Over HTTP POST losing data (Objective-C)

11,717

The problem is exactly what I suggested in my first comment. That is, base64 encoded data can contain '+' characters. In x-www-form-urlencoded data the receiver knows that '+' is an encoding of a space character. Thus since you aren't URL encoding your base64 value, any instances of '+' will cause the data to be corrupted when received.

The '+' characters in your initial data are turning into ' ' when received and stored. When you then output that value, it is invalid base64 encoded data.

If you examine the source of your working vs. non-working examples you'll see that the whitespace exists EXACTLY where there is a '+' in the original Base64 encoded value. Any newlines you're seeing are because whatever you're viewing the source in is wrapping lines at a ' ' character.

In your iOS code you need to properly encode the base64 encoded value, in your case all you really need to do is percent encode the '+' characters.

EDIT to add, in response to comment:

post = [post stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];
Share:
11,717

Related videos on Youtube

Jacob Clark
Author by

Jacob Clark

Updated on June 15, 2022

Comments

  • Jacob Clark
    Jacob Clark almost 2 years

    I currently have a HTTP POST Request and a Base64 Encoding Library, I encode my image to B64 then send it over HTTP via the POST method.

    I output the Base64 to XCodes console, copy and paste it and it works perfectly. Although the Base64 I store within the Database (MongoDB, Plain Text File etc) always comes out corrupt on the other end.

    Working Version (Copied and Pasted from XCode): http://dontpanicrabbit.com/api/working.php Broken Version (From MongoDB Database): http://dontpanicrabbit.com/api/grabimage.php

    If you view the source you'll notice they are the same but there is added whitespace into the broken version.

    The Objective-C code I am using is:

    MyImage.image = [info objectForKey:UIImagePickerControllerOriginalImage];
    
        NSData *imageData = UIImageJPEGRepresentation(MyImage.image, 0);
    
        [Base64 initialize];
        NSString *encoded = [Base64 encode:imageData];
    
        NSString *urlPOST = encoded;
        //NSLog(@"%@",encoded);
    
        NSString *varyingString1 = @"picture=";
        NSString *varyingString2 = urlPOST;
        NSString *post = [NSString stringWithFormat: @"%@%@", varyingString1, varyingString2];
        NSLog(@"%@", post);
        //NSString *post = @"image=%@",urlPOST;
        NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    
        NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
    
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:[NSURL URLWithString:@"url/api/insertimage.php"]];
        [request setHTTPMethod:@"POST"];
        [request setHTTPBody:postData];
        NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
        NSString *strResult = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
    

    PHP -> MongoDB Storage

    <?php
        try {
          // open connection to MongoDB server
          $conn = new Mongo('localhost');
    
          // access database
          $db = $conn->dablia;
    
          // access collection
          $collection = $db->images;
    
          // insert a new document
          $item = array(
            'picture' => $_POST['picture']
          );
          $collection->insert($item);
          echo 'Inserted document with ID: ' . $item['_id'];
    
          // disconnect from server
          $conn->close();
        } catch (MongoConnectionException $e) {
          die('Error connecting to MongoDB server');
        } catch (MongoException $e) {
          die('Error: ' . $e->getMessage());
        }
    ?>
    

    Output Code:

    <?php
    try {
      // open connection to MongoDB server
      $conn = new Mongo('localhost');
    
      // access database
      $db = $conn->dablia;
    
      // access collection
      $collection = $db->images;
    
      // execute query
      // retrieve all documents
      $cursor = $collection->find();
    
      // iterate through the result set
      // print each document
      foreach ($cursor as $obj) {
        echo '<img src="data:image/jpeg;base64,'.trim($obj['picture']).'">';
      }
    
      // disconnect from server
      $conn->close();
    } catch (MongoConnectionException $e) {
      die('Error connecting to MongoDB server');
    } catch (MongoException $e) {
      die('Error: ' . $e->getMessage());
    }
    ?>
    

    I have no idea why I seem to be corrupting over POST?