ios Upload Image and Text using HTTP POST

2018-12-31 09:10发布

Thanks for reading.

I am new to iOS and I am trying to upload an Image and a text using multi-part form encoding in iOS.

The curl equivalent is something like this: curl -F "param1=value1" -F "param2=@testimage.jpg" "http://some.ip.address:5000/upload"

The curl command above returns the expected correct response in JSON.

Problem: I keep getting a HTTP 400 request which means I am doing something wrong while composing the HTTP POST Body.

What I Did: For some reference, I tried Flickr API iOS app "POST size too large!" and Objective C: How to upload image and text using HTTP POST?. But, I keep getting a HTTP 400.

I tried the ASIHttpRequest but had a different problem there (the callback never got called). But, I didn't investigate further on that since I've heard the developer has stopped supporting the library: http://allseeing-i.com/[request_release];

Could someone please help me out?

10条回答
萌妹纸的霸气范
2楼-- · 2018-12-31 09:29

I can show you an example of uploading a .txt file to a server with NSMutableURLRequest and NSURLSessionUploadTask with help of a php script.

-(void)uploadFileToServer : (NSString *) filePath
{
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://YourURL.com/YourphpScript.php"]];
[request setHTTPMethod:@"POST"]; 
[request addValue:@"File Name" forHTTPHeaderField:@"FileName"];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject];

NSURLSessionUploadTask* uploadTask = [defaultSession uploadTaskWithRequest:request fromFile:[NSURL URLWithString:filePath] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
                                      {
                                          NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                          if (error || [httpResponse statusCode]!=202)
                                          {

                                              //Error
                                          }
                                          else
                                          {
                                             //Success
                                          }
                                          [defaultSession invalidateAndCancel];
                                      }];
[uploadTask resume];
}

php Script

<?php 
$request_body = @file_get_contents('php://input');
foreach (getallheaders() as $name => $value) 
{
    if ($FileName=="FileName") 
    {
        $header=$value;
        break;
    }
}   
$uploadedDir = "directory/";
@mkdir($uploadedDir);
file_put_contents($uploadedDir."/".$FileName.".txt",
$request_body.PHP_EOL, FILE_APPEND);
header('X-PHP-Response-Code: 202', true, 202);  
?>       
查看更多
人间绝色
3楼-- · 2018-12-31 09:30

XJones' answer worked like charm.

But he didn't mentioned/declared variables _params, BoundaryConstant and requestURL. So, i thought of posting that part as an add-on to his post, so that it may help others in future.

// Dictionary that holds post parameters. You can set your post parameters that your server accepts or programmed to accept.
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:[NSString stringWithString:@"1.0"] forKey:[NSString stringWithString:@"ver"]];
[_params setObject:[NSString stringWithString:@"en"] forKey:[NSString stringWithString:@"lan"]];
[_params setObject:[NSString stringWithFormat:@"%d", userId] forKey:[NSString stringWithString:@"userId"]];
[_params setObject:[NSString stringWithFormat:@"%@",title] forKey:[NSString stringWithString:@"title"]];

// the boundary string : a random string, that will not repeat in post data, to separate post data fields.
NSString *BoundaryConstant = [NSString stringWithString:@"----------V2ymHFg03ehbqgZCaKO6jy"];

// string constant for the post parameter 'file'. My server uses this name: `file`. Your's may differ 
NSString* FileParamConstant = [NSString stringWithString:@"file"];

// the server url to which the image (or the media) is uploaded. Use your server url here
NSURL* requestURL = [NSURL URLWithString:@""]; 

As i mentioned earler, this is not an answer by itself, just an addon to XJones' post.

查看更多
不流泪的眼
4楼-- · 2018-12-31 09:34

here's the working swift code translated from the code provided by @xjones. Thanks alot for your help mate. Yours was the only way that worked for me. I used this method to send 1 image and a another parameter to a webservice made in asp.net


                    let params = NSMutableDictionary()

                    let boundaryConstant  = "----------V2y2HFg03eptjbaKO0j1"

                    let file1ParamConstant = "file1"
                    params.setObject(device_id!, forKey: "deviceID")

                    let requestUrl = NSURL(string: "\(siteurl):\(port)/FileUpload/Upload")

                    let request = NSMutableURLRequest()

                    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
                    request.HTTPShouldHandleCookies=false
                    request.timeoutInterval = 30
                    request.HTTPMethod = "POST"

                    let contentType = "multipart/form-data; boundary=\(boundaryConstant)"

                    request.setValue(contentType, forHTTPHeaderField: "Content-Type")

                    let body = NSMutableData()

                    // parameters

                    for param in params {

                    body.appendData("--\(boundaryConstant)\r\n" .dataUsingEncoding(NSUTF8StringEncoding)! )
                    body.appendData("Content-Disposition: form-data; name=\"\(param)\"\r\n\r\n" .dataUsingEncoding(NSUTF8StringEncoding)!)
                    body.appendData("\(param.value)\r\n" .dataUsingEncoding(NSUTF8StringEncoding)!)

                    }
                    // images

                    // image begin
                    body.appendData("--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

                    body.appendData("Content-Disposition: form-data; name=\"\(file1ParamConstant)\"; filename=\"image.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
                    body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

                    body.appendData(passportImageData)
                    body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

                    // image end



                    body.appendData("--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

                    request.HTTPBody  = body
                    let postLength = "\(body.length)"
                    request.setValue(postLength, forHTTPHeaderField: "Content-Length")
                    request.URL = requestUrl

                    var serverResponse = NSString()

                    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
                        data, response, error in

                        if error != nil
                        {
                            print("error=\(error)")
                            return
                        }


                        print("response = \(response)")


                        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
                        print("responseString = \(responseString!)")
                        serverResponse = responseString!


                        }

                            task.resume()
查看更多
柔情千种
5楼-- · 2018-12-31 09:37
use below code. it will work fine for me.

+(void) sendHttpRequestWithArrayContent:(NSMutableArray *) array 
ToUrl:(NSString *) strUrl withHttpMethod:(NSString *) strMethod 
withBlock:(dictionary)block
{
if (![Utility isConnectionAvailableWithAlert:TRUE])
{
    [Utility showAlertWithTitle:@"" andMessage:@"No internet connection available"];
}


NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;

[request setURL:[NSURL URLWithString:strUrl]];
[request setTimeoutInterval:120.0];
[request setHTTPMethod:strMethod];

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

NSMutableData *body=[[NSMutableData alloc]init];

for (NSMutableDictionary *dict in array)
{
    if ([[dict valueForKey:[[dict allKeys]objectAtIndex:0]] isKindOfClass:[NSString class]])
    {
        [body appendData:[self contentDataFormStringWithValue:[dict valueForKey:[[dict allKeys]objectAtIndex:0]] withKey:[[dict allKeys]objectAtIndex:0]]];
    }
    else if ([[dict valueForKey:[[dict allKeys]objectAtIndex:0]] isKindOfClass:[UIImage class]])
    {
        [body appendData:[self contentDataFormImage:[dict valueForKey:[[dict allKeys]objectAtIndex:0]] withKey:[[dict allKeys]objectAtIndex:0]]];
    }
    else if ([[dict valueForKey:[[dict allKeys]objectAtIndex:0]] isKindOfClass:[NSMutableDictionary class]])
    {
        [body appendData:[self contentDataFormStringWithValue:[dict valueForKey:[[dict allKeys]objectAtIndex:0]] withKey:[[dict allKeys]objectAtIndex:0]]];
    }
    else
    {
        NSMutableData *dataBody = [NSMutableData data];
        [dataBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [dataBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"ipodfile.jpg\"\r\n",@"image"] dataUsingEncoding:NSUTF8StringEncoding]];
        [dataBody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

        [dataBody appendData:[dict valueForKey:[[dict allKeys]objectAtIndex:0]]];

        [body appendData:dataBody];
    }
}

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

[request setHTTPBody:body];

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
 {
     if (!data) {
         NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
          [dict setObject:[NSString stringWithFormat:@"%@",SomethingWentWrong] forKey:@"error"];
         block(dict);
         return ;
     }
     NSError *error = nil;
    // NSString *str=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
     NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
     NSLog(@"%@",dict);
     if (!dict) {
         NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
         [dict setObject:ServerResponceError forKey:@"error"];
         block(dict);
         return ;
     }
     block(dict);

 }];

}
+(NSMutableData*) contentDataFormStringWithValue:(NSString*)strValue 
withKey:(NSString *) key
{
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSMutableData *data=[[NSMutableData alloc]init];
[data appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[[NSString stringWithFormat:@"%@",strValue] dataUsingEncoding:NSUTF8StringEncoding]];  // title
return data;
}

+(NSMutableData*) contentDataFormImage:(UIImage*)image withKey:
(NSString *) key
{
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"ipodfile.jpg\"\r\n",key] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
NSData *imageData=UIImageJPEGRepresentation(image, 0.40);
[body appendData:imageData];

return body;
}
查看更多
皆成旧梦
6楼-- · 2018-12-31 09:38

For http post image and username and password sending through post method

 NSString *str=[NSString stringWithFormat:@"%@registration.php",appdel.baseUrl];
 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"];

 [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
 [body appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"a.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
 [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
 [body appendData:[NSData dataWithData:imgData]];
 [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=\"username\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

 [body appendData:[userName.text 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=\"email\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

 [body appendData:[eMail.text 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=\"pass\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

 [body appendData:[passWord.text dataUsingEncoding:NSUTF8StringEncoding]];
 [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];


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

 [body appendData:[countryCode 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);
 //
查看更多
冷夜・残月
7楼-- · 2018-12-31 09:46

Use AFNetworking; Put other parameters in the parameter dictionary and append the image data in form data.

//Upload Image Using AFNetworking

-(BOOL)uploadImageAFNetworkingWithURL:(NSString *)path andImage:(UIImage *)image andImageNameWithExtension:(NSString *)strImageName andParamDict:(NSDictionary *)dictParam andKeyForUploadingImage:(NSString *)keyUplaodImg{

    NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
    NSString *strError = EMPTY_STRING;

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
     manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager POST:path parameters:dictParam constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

        [formData appendPartWithFileData:imageData name:keyUplaodImg fileName:strImageName mimeType:@"image/jpeg"];

    } success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"success = %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"error = %@", error);
        NSLog(@"Response = %@", operation);
        [strError stringByAppendingString:STR_ERR_MESSAGE];
    }];
    if(strError.length>0){
        return NO;
    }else{
        return YES;
    }
}
查看更多
登录 后发表回答