2015-05-22 15 views
8

Qual è il modo corretto per codificare una richiesta PUT multipart utilizzando AFNetworking su iOS? (ancora Objective-C, non Swift)richiesta PUT multipart utilizzando AFNetworking

Ho guardato e sembra che AFNetworking possa fare più parti POST ma non PUT, qual è la soluzione?

Grazie

risposta

14

È possibile utilizzare multipartFormRequestWithMethod per creare un PUT richiesta di più parti con i dati desiderati.

Per esempio, in AFNetworking V3.x:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 

NSError *error; 
NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:@"http://example.com/rest/api/" parameters:@{@"foo" : @"bar"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
    NSString *value = @"qux"; 
    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; 
    [formData appendPartWithFormData:data name:@"baz"]; 
} error:&error]; 

NSURLSessionDataTask *task = [manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { 
    if (error) { 
     NSLog(@"%@", error); 
     return; 
    } 

    // if you want to know what the statusCode was 

    if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 
     NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; 
     NSLog(@"statusCode: %ld", statusCode); 
    } 

    NSLog(@"%@", responseObject); 
}]; 
[task resume]; 

Se AFNetworking 2.x, è possibile utilizzare AFHTTPRequestOperationManager:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 

NSError *error; 
NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:@"http://example.com/rest/api/" parameters:@{@"foo" : @"bar"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
    NSString *value = @"qux"; 
    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; 
    [formData appendPartWithFormData:data name:@"baz"]; 
} error:&error]; 

AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"%@", responseObject); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"%@", error); 
}]; 

[manager.operationQueue addOperation:operation]; 

aver illustrato come si possa creare tale richiesta, vale la pena notare che i server potrebbero non essere in grado di analizzarli. In particolare, PHP analizza le richieste multipart POST, ma non le richieste multipart PUT.

+0

Risposta accurata, funziona bene! Grazie mille – mindbomb

+0

grazie ha funzionato ... – Leena

+0

provato sopra il codice, ma sempre di errore "immagine" { folowing: [ "I dati presentati non era un file.Controlla il tipo di codifica nel modulo. " ] } –

0

è possibile creare un NSURLRequest costruito con metodo multipart modulo di richiesta s' il AFHTTPRequestSerialization

NSString *url = [[NSURL URLWithString:path relativeToURL:manager.baseURL] absoluteString]; 
id block = ^(id<AFMultipartFormData> formData) { 
    [formData appendPartWithFileData:media 
           name:@"image" 
          fileName:@"image" 
          mimeType:@"image/jpeg"]; 
}; 

NSMutableURLRequest *request = [manager.requestSerializer 
           multipartFormRequestWithMethod:@"PUT" 
           URLString:url 
           parameters:nil 
           constructingBodyWithBlock:block 
           error:nil]; 

[manager HTTPRequestOperationWithRequest:request success:successBlock failure:failureBlock]; 
0

mi si avvicinò con una soluzione in grado di gestire qualsiasi metodo supportato. Questa è una soluzione per PUT, ma puoi anche sostituirla con POST. Questo è un metodo in una categoria che chiamo sulla classe del modello di base.

- (void)updateWithArrayOfFiles:(NSArray *)arrayOfFiles forKey:(NSString *)key params:(NSDictionary *)params success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { 

     id block = [self multipartFormConstructionBlockWithArayOfFiles:arrayOfFiles forKey:key failureBlock:failure]; 

     NSMutableURLRequest *request = [[self manager].requestSerializer 
             multipartFormRequestWithMethod:@"PUT" 
             URLString:self.defaultURL 
             parameters:nil 
             constructingBodyWithBlock:block 
             error:nil]; 

     AFHTTPRequestOperation *operation = [[self manager] HTTPRequestOperationWithRequest:request success:success failure:failure]; 
     [operation start]; 
    } 

    #pragma mark multipartForm constructionBlock 

    - (void (^)(id <AFMultipartFormData> formData))multipartFormConstructionBlockWithArayOfFiles:(NSArray *)arrayOfFiles forKey:(NSString *)key failureBlock:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { 
     id block = ^(id<AFMultipartFormData> formData) { 
      int i = 0; 
      // form mimeType 
      for (FileWrapper *fileWrapper in arrayOfFiles) { 
       NSString *mimeType = nil; 
       switch (fileWrapper.fileType) { 
        case FileTypePhoto: 
         mimeType = @"image/jpeg"; 
         break; 
        case FileTypeVideo: 
         mimeType = @"video/mp4"; 
         break; 
        default: 
         break; 
       } 
       // form imageKey 
       NSString *imageName = key; 
       if (arrayOfFiles.count > 1) 
        // add array specificator if more than one file 
        imageName = [imageName stringByAppendingString: [NSString stringWithFormat:@"[%d]",i++]]; 
       // specify file name if not presented 
       if (!fileWrapper.fileName) 
        fileWrapper.fileName = [NSString stringWithFormat:@"image_%d.jpg",i]; 
       NSError *error = nil; 

       // Make the magic happen 
       [formData appendPartWithFileURL:[NSURL fileURLWithPath:fileWrapper.filePath] 
              name:imageName 
             fileName:fileWrapper.fileName 
             mimeType:mimeType 
              error:&error]; 
       if (error) { 
        // Handle Error 
        [ErrorManager logError:error]; 
        failure(nil, error); 
       } 
      } 
     }; 
     return block; 
    } 

Aso utilizza FileWrapper interfaccia

typedef NS_ENUM(NSInteger, FileType) { 
     FileTypePhoto, 
     FileTypeVideo, 
    }; 


@interface FileWrapper : NSObject 

@property (nonatomic, strong) NSString *filePath; 
@property (nonatomic, strong) NSString *fileName; 
@property (assign, nonatomic) FileType fileType; 

@end 
3

Ecco il codice per Afnetworking 3.0 e Swift che ha lavorato per me. Conosco il suo vecchio thread ma potrebbe essere utile per qualcuno!

let manager: AFHTTPSessionManager = AFHTTPSessionManager() 

    let URL = "\(baseURL)\(url)"   

    let request: NSMutableURLRequest = manager.requestSerializer.multipartFormRequestWithMethod("PUT", URLString: URL, parameters: parameters as? [String : AnyObject], constructingBodyWithBlock: {(formData: AFMultipartFormData!) -> Void in 
     formData.appendPartWithFileData(image!, name: "Photo", fileName: "photo.jpg", mimeType: "image/jpeg") 
     }, error: nil) 

    manager.dataTaskWithRequest(request) { (response, responseObject, error) -> Void in 

     if((error == nil)) { 
      print(responseObject) 
      completionHandler(responseObject as! NSDictionary,nil) 
     } 
     else { 
      print(error) 
      completionHandler(nil,error) 
     } 

     print(responseObject) 
     }.resume() 
0

per il corpo RAW:

NSData * data = someData; NSMutableURLRequest * requeust = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: [self getURLWith: urlService]]];

[reqeust setHTTPMethod:@"PUT"]; 
[reqeust setHTTPBody:data]; 
[reqeust setValue:@"application/raw" forHTTPHeaderField:@"Content-Type"]; 

NSURLSessionDataTask *task = [manager uploadTaskWithRequest:requeust fromData:nil progress:^(NSProgress * _Nonnull uploadProgress) { 

} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { 

}]; 
[task resume]; 
0

.h

+ (void)PUT:(NSString *)URLString 
parameters:(id)parameters 
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block 
    progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock 
    success:(void (^)(NSURLResponse *response, id responseObject))success 
    failure:(void (^)(NSURLResponse * response, NSError *error))failure 
     error:(NSError *__autoreleasing *)requestError; 

.m:

+ (void)PUT:(NSString *)URLString 
parameters:(id)parameters 
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block 
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock 
    success:(void (^)(NSURLResponse * _Nonnull response, id responseObject))success 
    failure:(void (^)(NSURLResponse * _Nonnull response, NSError *error))failure 
error:(NSError *__autoreleasing *)requestError { 

    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] 
            multipartFormRequestWithMethod:@"PUT" 
            URLString:(NSString *)URLString 
            parameters:(NSDictionary *)parameters 
            constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block 
            error:(NSError *__autoreleasing *)requestError]; 
    AFURLSessionManager *manager = [AFURLSessionManager sharedManager];//[AFURLSessionManager manager] 
    NSURLSessionUploadTask *uploadTask; 
    uploadTask = [manager uploadTaskWithStreamedRequest:(NSURLRequest *)request 
               progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock 
             completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { 
              if (error) { 
               failure(response, error); 
              } else { 
               success(response, responseObject); 
              } 
             }]; 

    [uploadTask resume]; 
} 

Proprio come l'afnetworking classico. Mettilo nella tua rete Util :)

Problemi correlati