This commit is contained in:
parent
70b7e0522c
commit
1c1b204513
2 changed files with 36 additions and 2 deletions
|
|
@ -501,6 +501,9 @@ extern NSString * const AFNetworkingReachabilityNotificationStatusItem;
|
|||
|
||||
#pragma mark -
|
||||
|
||||
extern NSUInteger const kAFUploadStream3GSuggestedPacketSize;
|
||||
extern NSUInteger const kAFUploadStream3GSuggestedDelay;
|
||||
|
||||
/**
|
||||
The `AFMultipartFormData` protocol defines the methods supported by the parameter in the block argument of `AFHTTPClient -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:`.
|
||||
*/
|
||||
|
|
@ -544,4 +547,15 @@ extern NSString * const AFNetworkingReachabilityNotificationStatusItem;
|
|||
- (void)appendPartWithFormData:(NSData *)data
|
||||
name:(NSString *)name;
|
||||
|
||||
/**
|
||||
Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream.
|
||||
|
||||
@param numberOfBytes Maximum packet size, in number of bytes. The default packet size for an input stream is 32kb.
|
||||
@param delay Duration of delay each time a packet is read. By default, no delay is set.
|
||||
|
||||
@discussion When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Setting a maximum packet size and delay according to the recommended values (`kAFUploadStream3GSuggestedPacketSize` and `kAFUploadStream3GSuggestedDelay`) lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, as of iOS 6, there is no definite way to distinguish between a 3G, EDGE, or LTE connection. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth.
|
||||
*/
|
||||
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
||||
delay:(NSTimeInterval)delay;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -708,6 +708,9 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
#endif
|
||||
}
|
||||
|
||||
NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16;
|
||||
NSUInteger const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||
|
||||
@interface AFHTTPBodyPart : NSObject
|
||||
|
||||
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
||||
|
|
@ -727,6 +730,8 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
|
||||
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
||||
|
||||
@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
|
||||
@property (nonatomic, assign) NSTimeInterval delay;
|
||||
@property (readonly) unsigned long long contentLength;
|
||||
@property (readonly, getter = isEmpty) BOOL empty;
|
||||
|
||||
|
|
@ -834,6 +839,13 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
[self.bodyStream appendHTTPBodyPart:bodyPart];
|
||||
}
|
||||
|
||||
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
||||
delay:(NSTimeInterval)delay
|
||||
{
|
||||
self.bodyStream.numberOfBytesInPacket = numberOfBytes;
|
||||
self.bodyStream.delay = delay;
|
||||
}
|
||||
|
||||
- (NSMutableURLRequest *)requestByFinalizingMultipartFormData {
|
||||
if ([self.bodyStream isEmpty]) {
|
||||
return self.request;
|
||||
|
|
@ -861,6 +873,8 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
@property (nonatomic, retain) NSMutableArray *HTTPBodyParts;
|
||||
@property (nonatomic, retain) NSEnumerator *HTTPBodyPartEnumerator;
|
||||
@property (nonatomic, retain) AFHTTPBodyPart *currentHTTPBodyPart;
|
||||
@property (nonatomic, retain) NSDate *lastReadAt;
|
||||
@property (nonatomic, assign) NSInteger lastBytesRead;
|
||||
@end
|
||||
|
||||
@implementation AFMultipartBodyStream
|
||||
|
|
@ -870,6 +884,8 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
||||
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
||||
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
||||
@synthesize numberOfBytesInPacket = _numberOfBytesInPacket;
|
||||
@synthesize delay = _delay;
|
||||
|
||||
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
||||
self = [super init];
|
||||
|
|
@ -879,6 +895,7 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
|
||||
self.stringEncoding = encoding;
|
||||
self.HTTPBodyParts = [NSMutableArray array];
|
||||
self.numberOfBytesInPacket = NSIntegerMax;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
@ -912,13 +929,16 @@ static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
|||
|
||||
NSInteger bytesRead = 0;
|
||||
|
||||
while ((NSUInteger)bytesRead < length) {
|
||||
while ((NSUInteger)bytesRead < MIN(length, self.numberOfBytesInPacket)) {
|
||||
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
|
||||
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bytesRead += [self.currentHTTPBodyPart read:&buffer[bytesRead] maxLength:length - bytesRead];
|
||||
if (self.delay > 0.0f) {
|
||||
[NSThread sleepForTimeInterval:self.delay];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue