Cocoa 使用NSOutputStream发布到url

Cocoa 使用NSOutputStream发布到url,cocoa,post,nsoutputstream,Cocoa,Post,Nsoutputstream,所以我只想向url发送一个POST请求。现在我尝试使用NSURLRequest/NSURLConnection,但遇到了问题,决定转到较低的级别,也是因为我想发送大文件,并认为直接处理流可能更好。但是输出流委托似乎从未被调用,而且我似乎找不到使用NSOutputStream的initWithURL的示例 NSURL *url = [NSURL URLWithString:NSString stringWithFormat: @"http://url"]; self.outputStream =

所以我只想向url发送一个POST请求。现在我尝试使用NSURLRequest/NSURLConnection,但遇到了问题,决定转到较低的级别,也是因为我想发送大文件,并认为直接处理流可能更好。但是输出流委托似乎从未被调用,而且我似乎找不到使用NSOutputStream的
initWithURL
的示例

NSURL *url = [NSURL URLWithString:NSString stringWithFormat: @"http://url"];
self.outputStream = [[NSOutputStream alloc] initWithURL:url append:NO];
[outputStream retain];
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];

似乎outputStream在init之后是空的,我无法理解这一点,因为我的url是一个有效的url——我可以从终端ping它并从其他来源发送数据。我做错了什么,或者有人能告诉我如何使用流将POST请求写入URL吗?谢谢。

您不能使用
NSOutputStream
向HTTP服务器发送POST请求

好的方法是创建一个
NSMutableURLRequest
并为该请求提供一个
HTTPBodyStream
,然后创建一个
NSURLConnection
来发送请求

HTTPBodyStream
是请求将从中读取正文的
NSInputStream
。您可以使用
NSData
对象或文件内容对其进行初始化


如果要提供自定义内容(例如,要作为
多部分/表单数据
请求的一部分上载文件),则可能需要对
NSInputStream
进行子类化。在这种情况下,我建议您看一看,它解释了如何解决在使用带有
NSURLConnection
的自定义输入流时出现的问题。或者您可以使用提供现成的多部分HTTP请求的。是的,您可以使用NSOutputStream发送HTTP GET/POST请求

1.创建并打开您的流

2.当流准备写入时,将通过以下方法发送
nsstreamventhassspaceavailable
事件:

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode

3.制作一个
CFHTTPMessageRef
&并写入数据

代码如下:

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
    switch (eventCode) {
    case NSStreamEventOpenCompleted:{
        // 
    }
        break;
    case NSStreamEventHasSpaceAvailable:{
        [self sendHTTPMessage];
    }
        break;
    default:{
        //
    }
        break;
}

- (void)sendHTTPMessage{
    //create a http GET message
    CFStringRef requestMethod = (CFStringRef)CFAutorelease(CFSTR("GET"));
    CFHTTPMessageRef httpRequest = (CFHTTPMessageRef)CFAutorelease(CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, (__bridge  CFURLRef)yourURL,kCFHTTPVersion1_1));
    //set HTTP header
    CFHTTPMessageSetHeaderFieldValue(httpRequest, (__bridge CFStringRef)@"Host", (__bridge CFStringRef)@"yourhost.com");
    CFHTTPMessageSetHeaderFieldValue(httpRequest, (__bridge CFStringRef)@"Connection", (__bridge CFStringRef)@"close");
    //set HTTP Body
    ...
    //let's send it
    CFDataRef serializedRequest = CFHTTPMessageCopySerializedMessage(httpRequest);
    NSData *requestData = (__bridge_transfer NSData *)serializedRequest;
    [self.outStream write:requestData.bytes maxLength:requestData.length];
    [self.outStream close];
}

请记住,关键点是将CFHTTPMessageRef转换为字节进行写入。

这听起来正是我需要的!谢谢你给我指明了正确的方向。我查看了ASIHTTPRequest,看起来我可以使用它,除了提供的类似乎是针对iOS的,从Mac示例复制文件会导致链接器错误。我错过什么了吗?或者你知道任何子类化NSInputStream的简单例子吗?我已经看过了,还没有找到一个清晰的例子。不管怎样,我找到了ASIHTTPRequest的安装说明:谢谢!