POST multipart / form-data with Objective-C

ainsi ce code HTML soumet les données dans le format correct pour moi.

<form action="https://www.example.com/register.php" method="post" enctype="multipart/form-data">
    Name: <input type="text" name="userName"><BR />
    Email: <input type="text" name="userEmail"><BR />
    Password: <input type="text" name="userPassword"><BR />
    Avatar: <input type="file" name="avatar"><BR />
    <input type="submit">
</form>

j'ai regardé dans un bon nombre d'articles sur la façon de faire un multipart/form-data POST sur iOS, mais aucun n'explique vraiment ce qu'il faut faire s'il y avait des paramètres normaux aussi bien que le téléchargement de fichier.

pourriez-vous s'il vous plaît m'aider avec le code pour poster ceci dans Obj-C?

Merci!

56
demandé sur Ali Almohsen 2014-06-16 23:07:55

4 réponses

le procédé est le suivant:

  1. Créer un dictionnaire avec le userName , userEmail , et userPassword paramètres".

    NSDictionary *params = @{@"userName"     : @"rob",
                             @"userEmail"    : @"rob@email.com",
                             @"userPassword" : @"password"};
    
  2. déterminer le chemin de l'image:

    NSString *path = [[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"];
    
  3. créer la demande:

    NSString *boundary = [self generateBoundaryString];
    
    // configure the request
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    
    // set content type
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];
    
    // create body
    
    NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName];
    
  4. C'est la méthode utilisée ci-dessus pour construire le corps de la requête:

    - (NSData *)createBodyWithBoundary:(NSString *)boundary
                            parameters:(NSDictionary *)parameters
                                 paths:(NSArray *)paths
                             fieldName:(NSString *)fieldName {
        NSMutableData *httpBody = [NSMutableData data];
    
        // add params (all params are strings)
    
        [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
            [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
        }];
    
        // add image data
    
        for (NSString *path in paths) {
            NSString *filename  = [path lastPathComponent];
            NSData   *data      = [NSData dataWithContentsOfFile:path];
            NSString *mimetype  = [self mimeTypeForPath:path];
    
            [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:data];
            [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
        }
    
        [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
        return httpBody;
    }
    
  5. ce qui précède utilise les méthodes d'utilité suivantes:

    @import MobileCoreServices;    // only needed in iOS
    
    - (NSString *)mimeTypeForPath:(NSString *)path {
        // get a mime type for an extension using MobileCoreServices.framework
    
        CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
        CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
        assert(UTI != NULL);
    
        NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
        assert(mimetype != NULL);
    
        CFRelease(UTI);
    
        return mimetype;
    }
    
    - (NSString *)generateBoundaryString {
        return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
    }
    
  6. soumettre ensuite la demande. Il y a beaucoup, beaucoup d'options ici.

    par exemple, si vous utilisez NSURLSession , vous pouvez créer NSURLSessionUploadTask :

    NSURLSession *session = [NSURLSession sharedSession];  // use sharedSession or create your own
    
    NSURLSessionTask *task = [session uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"error = %@", error);
            return;
        }
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"result = %@", result);
    }];
    [task resume];
    

    ou vous pouvez créer un NSURLSessionDataTask :

    request.HTTPBody = httpBody;
    
    NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"error = %@", error);
            return;
        }
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"result = %@", result);
    }];
    [task resume];
    

    le ci-dessus suppose que le serveur retourne juste la réponse du texte. Il est préférable que le serveur renvoie JSON, auquel cas vous utiliserez NSJSONSerialization plutôt que NSString méthode initWithData .

    de même, j'utilise les rendus de bloc d'achèvement de NSURLSession ci-dessus, mais n'hésitez pas à utiliser les rendus basés sur les délégués plus riches, aussi. Mais cela semble au-delà de la portée de cette question, donc je vous laisse faire.

Mais espérons que cela illustre l'idée.


je serais négligent si je n'avais pas pointé que, beaucoup plus facile que le ci-dessus, vous pouvez utiliser AFNetworking , en répétant les étapes 1 et 2 ci-dessus, mais en appelant juste:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; if web service returns JSON, remove this line
NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    NSError *error;
    if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"avatar" fileName:[path lastPathComponent] mimeType:@"image/png" error:&error]) {
        NSLog(@"error appending part: %@", error);
    }
}  progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    NSLog(@"responseObject = %@", responseObject);
} failure:^(NSURLSessionTask *task, NSError *error) {
    NSLog(@"error = %@", error);
}];

if (!task) {
    NSLog(@"Creation of task failed.");
}
157
répondu Rob 2017-03-26 06:39:35

AFFICHER plusieurs images à l'aide de plusieurs parties ou de données de formulaire avec Objective-C

-(void)multipleimageandstring
{
    NSString *urlString=@"URL NAME";

    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"];

    // file
    float low_bound = 0;
    float high_bound =5000;
    float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);//image1
    int intRndValue = (int)(rndValue + 0.5);
   NSString *str_image1 = [@(intRndValue) stringValue];

    UIImage *chosenImage1=[UIImage imageNamed:@"Purchase_GUI_curves-12 copy.png"];

    NSData *imageData = UIImageJPEGRepresentation(chosenImage1, 90);
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"files\"; filename=\"%@.png\"\r\n",str_image1] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];





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

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

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"adminId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:app.adminId] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"\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);

}
2
répondu manish gaurav 2016-07-29 08:08:29

essayez d'utiliser ceci à la fois pour la vidéo et les données d'image avec différents types de mime.

NSDictionary *param;

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

// 1. Create `AFHTTPRequestSerializer` which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request;

NSData *fileData;
if ([objDoc.url containsString:@".mp4"]) {
    manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"];
    [serializer setValue:@"video/mp4" forHTTPHeaderField:@"Content-Type"];
    manager.requestSerializer = serializer;
}

// 2. Create an `NSMutableURLRequest`.

NSLog(@"filename =%@",objDoc.url);
request= [serializer multipartFormRequestWithMethod:@"POST" URLString:strUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

    if ([objDoc.url containsString:@".mp4"]) {
        [formData appendPartWithFileData:fileData
                                    name:@"File"
                                fileName:@"video.mp4"
                                mimeType:@"video/mp4"];

    }else{
        [formData appendPartWithFileData:fileData
                                    name:@"File"
                                fileName:@"image.jpeg"
                                mimeType:@"image/jpeg"];
    }

} error:nil];

// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.

self.objeDocument.isUploading = [NSNumber numberWithInt:1];

self.operation = [manager HTTPRequestOperationWithRequest:request
                                                  success:^(AFHTTPRequestOperation *operation, id responseObject) {

                                                      NSLog(@"Success %@", responseObject);
                                                  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                      UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error!" message:@"The document attached has failed to upload." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                                                      [alert show];
                                                      [self.operation cancel];
                                                      NSLog(@"Failure %@", error.description);
                                                  }];


// 4. Set the progress block of the operation.
[self.operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                         long long totalBytesWritten,
                                         long long totalBytesExpectedToWrite) {
    NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
    float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;


}];

// 5. Begin!
[self.operation start];
1
répondu Arvind Patidar 2015-10-27 12:23:41

j'ai lutté avec cela pendant un certain temps, si vous cherchez à télécharger des images multiples ou d'autres types de fichiers, vous pouvez faire ce qui suit en utilisant AFNetworking 3.0

NSDictionary *params = @{key        : value,
                            ..... etc
                         };

 NSString *urlString = @"http://..... your endpoint url";

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON;  

NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    for (int x = 0 ; x< contentArray.count; x++) {
        AttachmentsModel *model = contentArray[x];

        if(model.type == ImageAttachmentType){
            [formData appendPartWithFileData:model.data name:model.name fileName:model.fileName mimeType:model.mimeType];

        }else if(model.type == AudioAttachmentType){
            NSURL *urlVideoFile = [NSURL fileURLWithPath:model.path];
            [formData appendPartWithFileURL:urlVideoFile name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];
        }else{
            [formData appendPartWithFileURL:model.url name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];

        }

    }
}  progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    [Utility stopLoading];

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

    id json = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];


    if (block) {

        //your response comes here
    }

} failure:^(NSURLSessionTask *task, NSError *error) {
    NSLog(@"error = %@", error);

}];

if (!task) {
    NSLog(@"Creation of task failed.");
}

et voici à quoi ressemble mon Modèled'attaches:

//  AttachmentsModel.h

typedef enum AttachmnetType{
    ImageAttachmentType,
    AudioAttachmentType,
    VideoAttachmentType
} AttachmnetType;

@interface AttachmentsModel : NSObject

@property (strong, nonatomic) NSString *path;
@property (strong, nonatomic) NSData *data;
@property (strong, nonatomic) NSString *mimeType;
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *fileName;
@property (strong, nonatomic) NSURL *url;
0
répondu Mutawe 2018-01-15 08:25:51