mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-05 09:39:09 +08:00
224 lines
6.2 KiB
Objective-C
224 lines
6.2 KiB
Objective-C
//
|
|
// RKParams.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 8/3/09.
|
|
// Copyright 2009 Two Toasters. All rights reserved.
|
|
//
|
|
|
|
#import "RKParams.h"
|
|
#import "../Support/RKLog.h"
|
|
|
|
// Set Logging Component
|
|
#undef RKLogComponent
|
|
#define RKLogComponent lcl_cRestKitNetwork
|
|
|
|
/**
|
|
* The boundary used used for multi-part headers
|
|
*/
|
|
NSString* const kRKStringBoundary = @"0xKhTmLbOuNdArY";
|
|
|
|
@implementation RKParams
|
|
|
|
+ (RKParams*)params {
|
|
RKParams* params = [[[RKParams alloc] init] autorelease];
|
|
return params;
|
|
}
|
|
|
|
+ (RKParams*)paramsWithDictionary:(NSDictionary*)dictionary {
|
|
RKParams* params = [[[RKParams alloc] initWithDictionary:dictionary] autorelease];
|
|
return params;
|
|
}
|
|
|
|
- (id)init {
|
|
self = [super init];
|
|
if (self) {
|
|
_attachments = [NSMutableArray new];
|
|
_footer = [[[NSString stringWithFormat:@"--%@--\r\n", kRKStringBoundary] dataUsingEncoding:NSUTF8StringEncoding] retain];
|
|
_footerLength = [_footer length];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[_attachments release];
|
|
[_footer release];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (RKParams*)initWithDictionary:(NSDictionary*)dictionary {
|
|
self = [self init];
|
|
if (self) {
|
|
for (NSString* key in dictionary) {
|
|
id value = [dictionary objectForKey:key];
|
|
[self setValue:value forParam:key];
|
|
}
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setValue:(id <NSObject>)value forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [[RKParamsAttachment alloc] initWithName:param value:value];
|
|
[_attachments addObject:attachment];
|
|
[attachment release];
|
|
|
|
return attachment;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setFile:(NSString*)filePath forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [[RKParamsAttachment alloc] initWithName:param file:filePath];
|
|
[_attachments addObject:attachment];
|
|
[attachment release];
|
|
|
|
return attachment;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setData:(NSData*)data forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [[RKParamsAttachment alloc] initWithName:param data:data];
|
|
[_attachments addObject:attachment];
|
|
[attachment release];
|
|
|
|
return attachment;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setData:(NSData*)data MIMEType:(NSString*)MIMEType forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [self setData:data forParam:param];
|
|
if (MIMEType != nil) {
|
|
attachment.MIMEType = MIMEType;
|
|
}
|
|
|
|
return attachment;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setData:(NSData*)data MIMEType:(NSString*)MIMEType fileName:(NSString*)fileName forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [self setData:data forParam:param];
|
|
if (MIMEType != nil) {
|
|
attachment.MIMEType = MIMEType;
|
|
}
|
|
if (fileName != nil) {
|
|
attachment.fileName = fileName;
|
|
}
|
|
|
|
return attachment;
|
|
}
|
|
|
|
- (RKParamsAttachment*)setFile:(NSString*)filePath MIMEType:(NSString*)MIMEType fileName:(NSString*)fileName forParam:(NSString*)param {
|
|
RKParamsAttachment* attachment = [self setFile:filePath forParam:param];
|
|
if (MIMEType != nil) {
|
|
attachment.MIMEType = MIMEType;
|
|
}
|
|
if (fileName != nil) {
|
|
attachment.fileName = fileName;
|
|
}
|
|
|
|
return attachment;
|
|
}
|
|
|
|
#pragma mark RKRequestSerializable methods
|
|
|
|
- (NSString*)HTTPHeaderValueForContentType {
|
|
return [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kRKStringBoundary];
|
|
}
|
|
|
|
- (NSUInteger)HTTPHeaderValueForContentLength {
|
|
return _length;
|
|
}
|
|
|
|
- (NSInputStream*)HTTPBodyStream {
|
|
// Open each of our attachments
|
|
[_attachments makeObjectsPerformSelector:@selector(open)];
|
|
|
|
// Calculate the length of the stream
|
|
_length = _footerLength;
|
|
for (RKParamsAttachment* attachment in _attachments) {
|
|
_length += [attachment length];
|
|
}
|
|
|
|
return (NSInputStream*)self;
|
|
}
|
|
|
|
#pragma mark NSInputStream methods
|
|
|
|
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)maxLength {
|
|
NSUInteger bytesSentInThisRead = 0, bytesRead;
|
|
NSUInteger lengthOfAttachments = (_length - _footerLength);
|
|
|
|
// Proxy the read through to our attachments
|
|
_streamStatus = NSStreamStatusReading;
|
|
while (_bytesDelivered < _length && bytesSentInThisRead < maxLength && _currentPart < [_attachments count]) {
|
|
if ((bytesRead = [[_attachments objectAtIndex:_currentPart] read:buffer + bytesSentInThisRead maxLength:maxLength - bytesSentInThisRead]) == 0) {
|
|
_currentPart ++;
|
|
continue;
|
|
}
|
|
|
|
bytesSentInThisRead += bytesRead;
|
|
_bytesDelivered += bytesRead;
|
|
}
|
|
|
|
// If we have sent all the attachments data, begin emitting the boundary footer
|
|
if ((_bytesDelivered >= lengthOfAttachments) && (bytesSentInThisRead < maxLength)) {
|
|
NSUInteger footerBytesSent, footerBytesRemaining, bytesRemainingInBuffer;
|
|
|
|
// Calculate our position in the stream & buffer
|
|
footerBytesSent = _bytesDelivered - lengthOfAttachments;
|
|
footerBytesRemaining = _footerLength - footerBytesSent;
|
|
bytesRemainingInBuffer = maxLength - bytesSentInThisRead;
|
|
|
|
// Send the entire footer back if there is room
|
|
bytesRead = (footerBytesRemaining < bytesRemainingInBuffer) ? footerBytesRemaining : bytesRemainingInBuffer;
|
|
[_footer getBytes:buffer + bytesSentInThisRead range:NSMakeRange(footerBytesSent, bytesRead)];
|
|
|
|
bytesSentInThisRead += bytesRead;
|
|
_bytesDelivered += bytesRead;
|
|
}
|
|
|
|
return bytesSentInThisRead;
|
|
}
|
|
|
|
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL)hasBytesAvailable {
|
|
return _bytesDelivered < _length;
|
|
}
|
|
|
|
- (void)open {
|
|
_streamStatus = NSStreamStatusOpen;
|
|
RKLogTrace(@"RKParams stream opened...");
|
|
}
|
|
|
|
- (void)close {
|
|
if (_streamStatus != NSStreamStatusClosed) {
|
|
_streamStatus = NSStreamStatusClosed;
|
|
|
|
RKLogTrace(@"RKParams stream closed. Releasing self.");
|
|
|
|
// NOTE: When we are assigned to the URL request, we get
|
|
// retained. We release ourselves here to ensure the retain
|
|
// count will hit zero after upload is complete.
|
|
[self release];
|
|
}
|
|
}
|
|
|
|
- (NSStreamStatus)streamStatus {
|
|
if (_streamStatus != NSStreamStatusClosed && _bytesDelivered >= _length) {
|
|
_streamStatus = NSStreamStatusAtEnd;
|
|
}
|
|
|
|
return _streamStatus;
|
|
}
|
|
|
|
#pragma mark Core Foundation stream methods
|
|
|
|
- (void)_scheduleInCFRunLoop:(NSRunLoop *)runLoop forMode:(id)mode {
|
|
}
|
|
|
|
- (void)_setCFClientFlags:(CFOptionFlags)flags callback:(CFReadStreamClientCallBack)callback context:(CFStreamClientContext)context {
|
|
}
|
|
|
|
@end
|