Использование NSOutputStream для POST для URL

Поэтому все, что я хочу сделать, это отправить запрос POST на URL. Теперь я попытался использовать NSURLRequest/NSURLConnection, но у меня возникли проблемы с этим, и я решил перейти на более низкий уровень, в том числе потому, что я хочу отправлять большие файлы, и подумал, что работа с потоками напрямую может быть лучше. Но делегат выходного потока никогда не вызывается, и я не могу найти примеры, использующие 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];

Кажется, что outputStream имеет значение null после инициализации, что я не могу понять, потому что мой URL-адрес является действительным URL-адресом - я могу пропинговать его из терминала и отправлять данные из других источников. Я делаю что-то не так, или кто-нибудь может сказать мне, как записать POST-запрос на URL с помощью потоков? Благодарю.

1 ответ

Решение

Вы не можете использовать NSOutputStream отправить запрос POST на HTTP-сервер.

Хороший метод заключается в создании NSMutableURLRequest и предоставить этот запрос с HTTPBodyStream затем создать NSURLConnection отправить запрос.

HTTPBodyStream является NSInputStream запрос будет читать тело от. Вы можете инициализировать его с помощью NSData объект или с содержимым файла.

Если вы хотите предоставить пользовательский контент (например, вы хотите загрузить файл как часть multipart/form-data запрос), вам может понадобиться подкласс NSInputStream, В таком случае, я предлагаю вам взглянуть на Как реализовать бесплатный подкласс NSInputStream CoreFoundation с мостовым соединением, в котором объясняется, как решить проблему, возникающую при использовании пользовательских потоков ввода с NSURLConnection, Или вы можете использовать ASIHTTPRequest, который предоставляет многокомпонентные HTTP-запросы из коробки.

Да, вы можете отправить HTTP-запрос GET/POST с помощью NSOutputStream.

1. создайте и откройте свой поток.

2. когда поток готов к записи, NSStreamEventHasSpaceAvailable событие будет отправлено методом:

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

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

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 в байты для записи.

Другие вопросы по тегам