如何在iOS上发送多部分HTTP请求?

时间:2022-03-08 20:15:58

I am trying to upload a photo onto a server on my iOS App using multipart method. However, I can't seem to get it to work. I am getting the error:

我正在尝试使用multipart方法将照片上传到iOS App上的服务器上。但是,我似乎无法让它发挥作用。我收到错误:

At least one of the pre-conditions you specified did not hold. Bucket POST must be of the enclosure-type multipart. I've looked this error and can't seem to figure out how I can solve this problem on my end. The Android version of the app works so the API should not be the problem?

您指定的至少一个前提条件不成立。 Bucket POST必须是机箱类型的多部分。我看了这个错误,似乎无法弄清楚我怎么能解决这个问题。 Android版本的应用程序工作,所以API应该不是问题?

Here is my code:

这是我的代码:

  //photo file 
  NSData *data = [[NSFileManager defaultManager] contentsAtPath:filePath];

  NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:uploadInfo.key forKey:@"key"];
[_params setObject:uploadInfo.aaki forKey:@"AWSAccessKeyId"];
[_params setObject:uploadInfo.acl forKey:@"acl"];
[_params setObject:uploadInfo.policy forKey:@"policy"];
[_params setObject:uploadInfo.signature forKey:@"signature"];
[_params setObject:uploadInfo.success_action_status forKey:@"success_action_status"];
[_params setObject:@"image/jpeg" forKey:@"Content-Type"];

NSURL* requestURL = [NSURL URLWithString:uploadInfo.path];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];

NSMutableData *body = [NSMutableData data];
 for (NSString *param in _params) {
 [body appendData:[[NSString stringWithFormat:@"%@", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
  }

 if (data) {
   [body appendData:data];
 }

[request setHTTPBody:body];

    [request setURL:requestURL];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

NSString *responseString = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
NSLog(@"%@",responseString);

2 个解决方案

#1


0  

Try as below.

请尝试以下方法。

//photo file 
NSData *data = [[NSFileManager defaultManager] contentsAtPath:filePath];
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:uploadInfo.key forKey:@"key"];
[_params setObject:uploadInfo.aaki forKey:@"AWSAccessKeyId"];
[_params setObject:uploadInfo.acl forKey:@"acl"];
[_params setObject:uploadInfo.policy forKey:@"policy"];
[_params setObject:uploadInfo.signature forKey:@"signature"];
[_params setObject:uploadInfo.success_action_status forKey:@"success_action_status"];

NSURL* requestURL = [NSURL URLWithString:uploadInfo.path];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];

//Create boundary, it can be anything
NSString *boundary = @"------VohpleBoundary4QuqLuM1cE5lMwCy";

// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];

NSMutableData *body = [NSMutableData data];
for (NSString *param in _params) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
NSString *FileParamConstant = @"image";   // Key of webservice in which you need to send image
// add image data
if (data) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:data];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
//Close off the request with the boundary
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];

// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setURL:requestURL];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

#2


0  

Try with another simple code.

尝试另一个简单的代码。

NSDictionary *aParams =@{}; //your param dictionary here

    UIImage *aImage = [UIImage imageNamed:@"your image here"]; //set yout image here
    NSString *aStrParamName = @"image parameter name here";// set parameter name of image here

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"uploadInfo.path"]];// url here
    [request setHTTPMethod:@"POST"];
    [request setTimeoutInterval:30];
    NSString *uuidStr = [[NSUUID UUID] UUIDString];
    [request addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", uuidStr] forHTTPHeaderField:@"Content-Type"];

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

    NSData *imagedata = UIImageJPEGRepresentation(aImage, (CGFloat)0.6);
    NSData *fileData = UIImagePNGRepresentation([UIImage imageWithData:imagedata]);
    NSData *data = [self createBodyWithBoundary:uuidStr withDictData:aParams data:fileData filename:aStrParamName];

    NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSAssert(!error, @"%s: uploadTaskWithRequest error: %@", __FUNCTION__, error);

        // parse and interpret the response `NSData` however is appropriate for your app

        NSString *aStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"ResponseString:%@",aStr);

        NSMutableDictionary *aMutDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"responce:%@",aMutDict);

        });
    }];
    [task resume];

also add below method

还添加以下方法

- (NSData *)createBodyWithBoundary:(NSString *)boundary withDictData:(NSDictionary *)aDict data:(NSData*)data filename:(NSString *)paramName
{
    NSMutableData *body = [NSMutableData data];

    if (data) {
        //only send these methods when transferring data as well as username and password
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", paramName,@"image.png"] dataUsingEncoding:NSUTF8StringEncoding]];
#warning if you have to chane name of image then change. if there is any error then chane other wise go as it is..
        [body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", @"image/png"] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:data];
        [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    }

    for (NSString *aKey in aDict.allKeys) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", aKey,aDict[aKey]] dataUsingEncoding:NSUTF8StringEncoding]];

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

    return body;
}

#1


0  

Try as below.

请尝试以下方法。

//photo file 
NSData *data = [[NSFileManager defaultManager] contentsAtPath:filePath];
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:uploadInfo.key forKey:@"key"];
[_params setObject:uploadInfo.aaki forKey:@"AWSAccessKeyId"];
[_params setObject:uploadInfo.acl forKey:@"acl"];
[_params setObject:uploadInfo.policy forKey:@"policy"];
[_params setObject:uploadInfo.signature forKey:@"signature"];
[_params setObject:uploadInfo.success_action_status forKey:@"success_action_status"];

NSURL* requestURL = [NSURL URLWithString:uploadInfo.path];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];

//Create boundary, it can be anything
NSString *boundary = @"------VohpleBoundary4QuqLuM1cE5lMwCy";

// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];

NSMutableData *body = [NSMutableData data];
for (NSString *param in _params) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
NSString *FileParamConstant = @"image";   // Key of webservice in which you need to send image
// add image data
if (data) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:data];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
//Close off the request with the boundary
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];

// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setURL:requestURL];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

#2


0  

Try with another simple code.

尝试另一个简单的代码。

NSDictionary *aParams =@{}; //your param dictionary here

    UIImage *aImage = [UIImage imageNamed:@"your image here"]; //set yout image here
    NSString *aStrParamName = @"image parameter name here";// set parameter name of image here

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"uploadInfo.path"]];// url here
    [request setHTTPMethod:@"POST"];
    [request setTimeoutInterval:30];
    NSString *uuidStr = [[NSUUID UUID] UUIDString];
    [request addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", uuidStr] forHTTPHeaderField:@"Content-Type"];

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

    NSData *imagedata = UIImageJPEGRepresentation(aImage, (CGFloat)0.6);
    NSData *fileData = UIImagePNGRepresentation([UIImage imageWithData:imagedata]);
    NSData *data = [self createBodyWithBoundary:uuidStr withDictData:aParams data:fileData filename:aStrParamName];

    NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSAssert(!error, @"%s: uploadTaskWithRequest error: %@", __FUNCTION__, error);

        // parse and interpret the response `NSData` however is appropriate for your app

        NSString *aStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"ResponseString:%@",aStr);

        NSMutableDictionary *aMutDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"responce:%@",aMutDict);

        });
    }];
    [task resume];

also add below method

还添加以下方法

- (NSData *)createBodyWithBoundary:(NSString *)boundary withDictData:(NSDictionary *)aDict data:(NSData*)data filename:(NSString *)paramName
{
    NSMutableData *body = [NSMutableData data];

    if (data) {
        //only send these methods when transferring data as well as username and password
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", paramName,@"image.png"] dataUsingEncoding:NSUTF8StringEncoding]];
#warning if you have to chane name of image then change. if there is any error then chane other wise go as it is..
        [body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", @"image/png"] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:data];
        [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    }

    for (NSString *aKey in aDict.allKeys) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", aKey,aDict[aKey]] dataUsingEncoding:NSUTF8StringEncoding]];

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

    return body;
}