So all I want to do is send a POST request to a url. Now I tried using NSURLRequest/NSURLConnection, but was having problems with that and decided to move to a lower level, also because I want to send large files and thought dealing directly with streams might be better. But the output stream delegate never seems to be called, and I can't seem to find examples using NSOutputStream's 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];

It seems that the outputStream is null after the init, which I can't understand because my url is a valid url--I can ping it from the terminal and send data from other sources. Am I doing something wrong, or can anyone tell me how to write a POST request to a URL using streams? Thanks.

有帮助吗?

解决方案

You cannot use NSOutputStream to send a POST request to a HTTP server.

The good method is to create a NSMutableURLRequest and provide that request with a HTTPBodyStream then create a NSURLConnection to send the request.

The HTTPBodyStream is an NSInputStream the request will read the body from. You may initialize it with a NSData object or with the contents of a file.

If you want to provide a custom content (for example, you want to upload a file as part of a multipart/form-data request), you may need to subclass NSInputStream. In such case, I suggest you to have a look at How to implement CoreFoundation toll-free bridged NSInputStream subclass, which explains how to address an issue that occurs when using custom input streams with NSURLConnection. Or you may use ASIHTTPRequest which provides multipart HTTP requests out of the box.

其他提示

Yes, you can send the HTTP GET/POST request using NSOutputStream.

1.make & open your stream.

2.when the stream is ready to write, the NSStreamEventHasSpaceAvailable event will be send in method:

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

https://developer.apple.com/documentation/foundation/nsstreamdelegate/1410079-stream?language=objc

3.make a CFHTTPMessageRef & and write the data.

code like this:

- (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];
}

Remember, the key point is converting CFHTTPMessageRef to bytes to write.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top