0

I'm trying to upload an image to an API and then use the result. When using Postman, everything runs successfully. When I used the export feature to convert the code to Objective-C, I tried running it, but I'm getting a status code 400 (my parameters are invalid).

Here is the Postman request: enter image description here

enter image description here

Here is my own code:

    // Get image name
    NSURL *refURL = [info valueForKey:UIImagePickerControllerReferenceURL];
    PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[refURL] options:nil];
    NSString *filename = [[result firstObject] filename];

    // Get image file path and append file name onto it
    NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
    [imageData writeToFile:path atomically:YES];

    NSDictionary *headers = @{ @"content-type": @"multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
                               @"Content-Type": @"multipart/form-data",
                               @"Accept": @"application/json",
                               @"Authorization": @"Token 60f6be2a21bdf731d86a8817b440a1afba692fed",
                               @"Cache-Control": @"no-cache",
                               @"Postman-Token": @"7d262730-0c7d-66dc-bbbb-43f40dbfe8ce" };
    NSArray *parameters = @[ @{ @"name": @"task", @"value": @"dc9ef71a-b8a0-4a12-90fd-83d717cf887f" },
                             @{ @"name": @"image_file", @"fileName": path } ];
    NSString *boundary = @"----WebKitFormBoundary7MA4YWxkTrZu0gW";    

    NSError *error;
    NSMutableString *body = [NSMutableString string];
    for (NSDictionary *param in parameters) {
        [body appendFormat:@"--%@\r\n", boundary];
        if (param[@"fileName"]) {
            [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"; filename=\"%@\"\r\n", param[@"name"], param[@"fileName"]];
            [body appendFormat:@"Content-Type: %@\r\n\r\n", param[@"contentType"]];
            [body appendFormat:@"%@", [NSString stringWithContentsOfFile:param[@"fileName"] encoding:NSASCIIStringEncoding error:&error]]; 

            if (error) {
                NSLog(@"%@", error);
            }
        } else {
            [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"\r\n\r\n", param[@"name"]];
            [body appendFormat:@"%@", param[@"value"]];
        }
    }
    [body appendFormat:@"\r\n--%@--\r\n", boundary];
    NSData *postData = [body dataUsingEncoding:NSASCIIStringEncoding]; 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.vize.ai/v1/classify/"]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:10.0];
    [request setHTTPMethod:@"POST"];
    [request setAllHTTPHeaderFields:headers];
    [request setHTTPBody:postData];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    if (error) {
                                                        NSLog(@"%@", error);
                                                    } else {
                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                        NSLog(@"%@", httpResponse);
                                                    }
                                                }];
    [dataTask resume];

(It's not shown here, but I'm trying to use an image that the user will select from an image picker.) Why am I getting a status code 400 and how can I get the correct result?

fi12
  • 495
  • 11
  • 30
  • What is `fileName`? You have `filename`, but I see no `fileName`. – l'L'l Feb 23 '18 at 02:28
  • @l'L'l `fileName` is the name of one of the parameters; in this case, it is the name of the image I'm uploading. `fileName` is the default name for an image file that Postman assigns. – fi12 Feb 23 '18 at 02:29
  • Alright, the makes sense, so then what is `@param['name']`? – l'L'l Feb 23 '18 at 02:30
  • @l'L'l I'm not entirely sure. I'm new to Postman, but I'm assuming that's Postman's field name for the image file, something like `@"name": @"image_file"` – fi12 Feb 23 '18 at 02:39
  • Have you also tried using `NSUTF8StringEncoding` instead of `NSASCIIStringEncoding`? – l'L'l Feb 23 '18 at 02:43
  • @l'L'l I have, but that gives me an error because the file format my image is in cannot be encoded with `NSUTF8StringEncoding`. In fact, `NSUTF8StringEncoding` is what Postman originally gave me as code, but I changed it to `NSASCIIStringEncoding` to stop the error from occurring. – fi12 Feb 23 '18 at 02:44
  • Well, you'll likely want to `base64` encode/decode the image while using `utf8` (https://stackoverflow.com/a/44927586/499581) or setup a mime-type handler (https://stackoverflow.com/a/24252378/499581). – l'L'l Feb 23 '18 at 02:49
  • @l'L'l What is the difference between the two methods? Do both work as well as the other? – fi12 Feb 23 '18 at 02:51
  • The first example is basically illustrating a simple upload method using `base64` and `NSUTF8StringEncoding`, the second one is showing how multipart form can be used, which is more similar to what you have. I think the `400 Error` you are getting though is because the encoding is incorrect. – l'L'l Feb 23 '18 at 02:55
  • 1
    @l'L'l Alright, thanks for all the help. – fi12 Feb 23 '18 at 02:56
  • Are you sure it's OK to hardcode the token like that? I bet you need to call the classify URL first, get the token from that, then use that in a second request to actually post the image. – jsd Feb 25 '18 at 23:25
  • @jsd No, I'm pretty sure the token can be hardcoded. Postman works fine with it. – fi12 Feb 26 '18 at 00:32
  • @jsd Do you have any other suggestions? – fi12 Feb 28 '18 at 03:12
  • Want to make sure, are you trying to upload an image? I don't see any image data being added to the body post anywhere! I see you have saved the image to a temporary local directory, and are trying to use `[NSString stringWithContentsOfFile:param[@"fileName"] encoding:NSASCIIStringEncoding error:&error]]` I'm guessing to add the image to the post? I'm pretty sure that only works for text contents! Can you add some log statements to see what exactly you are sending where? It might help clear things up! – A.J. S. Mar 07 '18 at 06:48
  • @AJ.S Yes, I'm trying to upload an image. Are you sure that only works for text? What log statements would be helpful? – fi12 Mar 07 '18 at 13:07
  • @AJ.S Do you have any suggestions? – fi12 Mar 07 '18 at 23:43

0 Answers0