37

I've successfully created two different methods where each of them can upload either an image or text. But I am having problem writing a method that can post both text and image simultaneously!

// Here's my new method witch worked fine thanx to @sgosha:

- (void) upload {
    NSString *urlString = @"http://www.examplescript.com";
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];

    NSMutableData *body = [NSMutableData data];


    NSString *boundary = [NSString stringWithString:@"---------------------------14737809831466499882746641449"];
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];

    // file
    NSData *imageData = UIImageJPEGRepresentation(imageView.image, 90);

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"Content-Disposition: attachment; name=\"userfile\"; filename=\".jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

    // Text parameter1
    NSString *param1 = @"parameter text";
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"parameter1\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:param1] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

    // Another text parameter
    NSString *param2 = @"Parameter 2 text";
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"parameter2\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:param2] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

    // close form
    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    // set request body
    [request setHTTPBody:body];

    //return and test
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

    NSLog(@"%@", returnString);
}

//Old question: Obviously this was too easy and didn't work! I do not get any error in the console or anything, and the image is uploaded, but the text is not sent. Any ideas?

Btw: The server-side script is a very simple php script.

4
  • Maybe you can use ASIHTTPRequest to do it easily. Commented Mar 24, 2011 at 16:11
  • As of 17 jan 2013 look at the AFNetworking library on github. It's the best way to upload multipart/form data on http and https. It uses block. Makes clean and nice code. Commented Jan 17, 2013 at 2:09
  • 2
    May you share the php script? Commented Apr 22, 2014 at 17:05
  • 1
    Find the answer here Uploading Text File to php server Commented Feb 15, 2016 at 4:07

4 Answers 4

34

Try this (EDITED):

NSMutableData *body = [NSMutableData data];

// file
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Disposition: attachment; name=\"userfile\"; filename=\".jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

// text parameter
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"parameter1\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[parameterValue1 dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

// another text parameter
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"parameter2\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[parameterValue2 dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

// close form
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

// set request body
[request setHTTPBody:body];
Sign up to request clarification or add additional context in comments.

7 Comments

Is "attachment" the only edit you've done here? If so, where should i pass the text? Would this just state that the image is sent as an attachment, and that I could then send the text in code following the boundary but before the setHTTPBody-call?
Tnx, for quality code:D Worked perfectly now, will update the original post with my method wich now works fine!
thanks for this. Really helped. Was totally stuck on how to send a text param along with the image
Please consider updating to use Content-Disposition:form-data;charset=UTF-8;name=... as this will match the encoding NSUTF8StringEncoding. Non-english characters pasted into a form create are unusable to the server with this solution as posted
What is boundary? Can anyone explain please?
|
7

I also wanted to upload an image along with other data in the same POST, most information about uploading images is just for uploading an image alone in one server connection, here is how I solved this.

This is the PHP

<?php
/* As you can see there are more values not only the image */
$variableOne    = $_POST['variableOne'];
$variableTwo    = $_POST['variableTwo'];
$variableThree  = $_POST['variableThree'];
$variableFour   = $_POST['variableFour'];
$variableFive   = $_POST['variableFive'];
$variableSix    = $_POST['variableSix'];
$variableSeven  = $_POST['variableSeven'];
$variableEight  = $_POST['variableEight'];
$variableNine   = $_POST['variableNine'];
$variableTen    = $_POST['variableTen'];

/* Our image */
$image = $_REQUEST['image'];

/* This is for trying to get a unique name for the image file, since maybe you want to store large amount of images */
$currentDate = date("Y-m-d");
$name  = "" . $currentDate . microtime() . rand(0, 999) . rand(0, 999) . rand(0, 999) . ".jpg";

/* 
 * Here comes the image stuff
 */
if (file_exists($name)) {
    echo "File already exists";
} else {
        /* Decoding image */
        $binary = base64_decode($image);

        /* Opening image */
        $file = fopen($name, 'wb');

        /* Writing to server */
        fwrite($file, $binary);

        /* Closing image file */
        fclose($file);

        echo "Added";
    }   
}   
?>

Then in Xcode copy and paste this method (taken from Creating a base-64 string from NSData)

- (NSString*)base64forData:(NSData*) theData {
    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;

    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }

    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}

In YourViewController.h file

@interface YourViewController : UIViewController {
    NSURLConnection *serverConnection;
    NSMutableData *returnData;
}

This is the server connection code

NSURL *sendURL = [NSURL URLWithString:@"http://yourdomainname/imagefolder/phpscript.php"];

NSMutableURLRequest *sendRequest = [NSMutableURLRequest requestWithURL:sendURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];

[sendRequest setHTTPMethod:@"POST"];

[sendRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSData *imageData = UIImageJPEGRepresentation(yourImage, 1.0);

NSString *encodedString = [[self base64forData:imageData] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];

NSString *dataToSend = [[NSString alloc] initWithFormat:@"variableOne=%@&variableTwo=%@&variableThree=%@&variableFour=%@&variableFive=%@&variableSix=%@&variableSeven=%@&variableEight=%@&variableNine=%@&variableTen=%@&image=%@", valueOne, valueTwo, valueThree, valueFour, valueFive, valueSix, valueSeven, valueEight, valueNine, valueTen, encodedString];

[sendRequest setHTTPBody:[dataToSend dataUsingEncoding:NSUTF8StringEncoding]];

serverConnection = [[NSURLConnection alloc] initWithRequest:sendRequest delegate:self];

[serverConnection start];

Set delegate methods for server connection

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    returnData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [returnData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (connection == serverConnection) {
        NSString *responseString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

        NSLog(@"Response: %@", responseString);

        if ([responseString isEqualToString:@"Added"]) {

            /* Make something on success */

        } else {

            /* Make something else if not completed with success */

        }
    }
}

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    /* Make something on failure */
}

1 Comment

great example...works perfectly. Thanks for the PHP side of it too!
2

This code works for me with 1 image and 7 other parameters using POST Request

Make sure to change your variable names plus values and also image parameter name plus 'showPhoto' which is my IBOutlet UIImageView object 'name' shows URL parameter name.

NSString *str=@"http://xxx.xxx.xxx.xx/xxxx/xxxxx/xxxxx.php?action=add_place"; NSString *urlString = [NSString stringWithFormat:@"%@",str];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSMutableData *body = [NSMutableData data];
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];

 NSData *imageData = UIImageJPEGRepresentation(_showPhoto.image, 90);

[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"host_pic\"; filename=\"parkN.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

//  parameter username

[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userID\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"17" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];


//  parameter token
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"longitude\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"50.0011" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

//  parameter token
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"latitude\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"50.0011" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

// parameter method
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"place_name\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"lahore" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];


//parameter method
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"place_description\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"lahore" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

//parameter method
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"zip_code\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"123456" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

//parameter method
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"phone_number\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@"033333333" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];


// close form
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];


// setting the body of the post to the reqeust
[request setHTTPBody:body];


NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dict);

Comments

0

If you want to name the image:

 NSMutableString *nombreImagen= [[NSMutableString alloc]init];
    [nombreImagen appendString:@"Content-Disposition: attachment; name=\"file\"; filename=\""];
    [nombreImagen appendString:@"hoy"];
    [nombreImagen appendString:@".jpg\"\r\n"];
    .......

   [body appendData:[[NSString stringWithString:nombreImagen] dataUsingEncoding:NSUTF8StringEncoding]];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.