使用AFNetworking的多部分PUT请求
在iOS上使用AFNetworking编写多部分PUT请求的正确方法是什么? (仍然是Objective-C,而不是Swift)
我看起来似乎AFNetworking可以做多部分POST
而不是PUT
,那是什么解决方案?
谢谢
您可以使用multipartFormRequestWithMethod
创建具有所需数据的多部分PUT
请求。
例如,在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 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];
如果AFNetworking 2.x,您可以使用AFHTTPRequestOperationManager
:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSError *error; NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:@"http://example.com/rest/api/" parameters:@{@"foo" : @"bar"} constructingBodyWithBlock:^(id 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];
已经说明了如何创建这样的请求,值得注意的是服务器可能无法解析它们。 值得注意的是,PHP解析多部分POST
请求,但不解析多部分PUT
请求。
这是Afnetworking 3.0和Swift的代码,对我有用。 我知道它的旧线程但对某人来说可能很方便!
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()
您可以创建使用AFHTTPRequestSerialization
的多部分表单请求方法构造的NSURLRequest
NSString *url = [[NSURL URLWithString:path relativeToURL:manager.baseURL] absoluteString]; id block = ^(id 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];
我想出了一个可以处理任何支持方法的解决方案。 这是PUT的解决方案,但您也可以用POST替换它。 这是我在基础模型类上调用的类别中的方法。
- (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 formData))multipartFormConstructionBlockWithArayOfFiles:(NSArray *)arrayOfFiles forKey:(NSString *)key failureBlock:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { id block = ^(id 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; }
它使用FileWrapper接口
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
对于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];
。H
+ (void)PUT:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id 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 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 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]; }
就像经典的afnetworking一样。 把它放到你的网络工作实用程序:)