问题
I am uploading a photo using AFNetworking and I am getting the infamous "request body stream exhausted" error.
This is my code:
(_manager
is a AFHTTPRequestOperationManager
)
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
AFHTTPRequestOperation *operation = [_manager POST:address parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:@"file" fileName:@"image.jpg" mimeType:@"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success!");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(@"Written: %lld", totalBytesWritten);
}];
I get the error on both my iPhone 5S and my iPhone 4, both using wifi and 4G/3G. The issue is consistent and occurs every time, just when the upload is suppose to finish. The weird thing is that it use to work on these phones as well, but some days ago I suddenly started getting the error. Also, my colleague has no problems on his iPhone 5, both on wifi and 4G, running the same code. All phones run iOS 7.
I know that some people are getting this error when on 3G, and the solution in that situation is to use the throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay
method. However, this has had no affect in my case, and I get the error both on wifi and mobile.
I am able to perform the upload using curl
from my computer which is on the same network.
回答1:
I finally found a solution in this answer: https://stackoverflow.com/a/21304062/569507
However, in stead of subclassing the AFHTTPRequestOperation
as suggested, I simply made a category on it (or actually on its parent class AFURLConnectionOperation
which implements the NSURLConnectionDataDelegate
protocol) that contains the connection:needNewBodyStream
method. This is all that is needed. The rest of my code remains unaltered.
AFURLConnectionOperation+Recover.h
#import "AFURLConnectionOperation.h"
@interface AFURLConnectionOperation (Recover)
- (NSInputStream *)connection:(NSURLConnection *)connection needNewBodyStream:(NSURLRequest *)request;
@end
AFURLConnectionOperation+Recover.m
#import "AFURLConnectionOperation+Recover.h"
@implementation AFURLConnectionOperation (Recover)
- (NSInputStream *)connection:(NSURLConnection *)connection needNewBodyStream:(NSURLRequest *)request
{
if ([request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
return [request.HTTPBodyStream copy];
}
return nil;
}
@end
回答2:
NSData *imageData = UIImageJPEGRepresentation(img,1.0); long long testBytes = 0;
for (int i=0; i<[arrImages count];i++)
{
UIImage *img =[arrImages objectAtIndex:i];
img=[AppManager scaleDownImage:img];
NSData *imageData1 = UIImageJPEGRepresentation(img,1.0);
testBytes +=[imageData1 length]+130;
}
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:@"POST" URLString:[NSString stringWithFormat:@"%@%@",kBaseURL,kChallengeURL] parameters:aDic constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData
name:kProfileImage
fileName:@"myimage.jPEG"
mimeType:@"image/jpeg"];
}
error:nil];
//
// [serializer multipartFormRequestWithMethod:@"POST" URLString:[NSString stringWithFormat:@"%@%@",kBaseURL,kChallengeURL]
// parameters:aDic
// constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// [formData appendPartWithFileData:imageData
// name:@"attachment"
// fileName:@"myimage.jpg"
// mimeType:@"image/jpeg"];
// }];
// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
if ([[responseObject objectForKey:kStatus] intValue]==1)
{
NSArray *arrImages = [app.dicCreateChallangeDetail objectForKey:kProfileImage];
if ([arrImages count]==1)
{
[AppManager sharedManager].enCheckCreateService = eCreateWebserviceInStopped;
[[NSNotificationCenter defaultCenter]postNotificationName:kNotificationEnableTabBarButton object:nil userInfo:nil];
self.view.userInteractionEnabled = YES;
self.navigationItem.leftBarButtonItem.enabled = YES;
[self performSelector:@selector(goToHomeScreen) withObject:nil afterDelay:0.0];
}
else if ([arrImages count]>1)
{
[self uploadRestImages:[responseObject objectForKey:kChallengeId]];
}
}
else
{
[AppManager sharedManager].enCheckCreateService = eCreateWebserviceInStopped;
self.view.userInteractionEnabled = YES;
self.navigationItem.leftBarButtonItem.enabled = YES;
[Utils showAlertView:kAlertTitle message:[responseObject objectForKey:kMessage] delegate:nil cancelButtonTitle:kAlertBtnOK otherButtonTitles:nil];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
//NSLog(@"Failure %@", error.description);
[AppManager sharedManager].enCheckCreateService = eCreateWebserviceInStopped;
self.view.userInteractionEnabled = YES;
self.navigationItem.leftBarButtonItem.enabled = YES;
[Utils showAlertView:kAlertTitle message:@"Failed. Try again" delegate:nil cancelButtonTitle:kAlertBtnOK otherButtonTitles:nil];
[[NSNotificationCenter defaultCenter]postNotificationName:kNotificationEnableTabBarButton object:nil userInfo:nil];
}];
// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
long long totalBytesWritten,
long long totalBytesExpectedToWrite) {
NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%lld",totalBytesWritten],@"written",[NSString stringWithFormat:@"%lld",totalBytesExpectedToWrite],@"Totlal",nil];
[[NSNotificationCenter defaultCenter]postNotificationName:kNotificationRefreshHomePage object:dict userInfo:nil];
}];
// 5. Begin!
[operation start];
来源:https://stackoverflow.com/questions/24852773/error-when-uploading-photo-with-afnetworking