Постановка в очередь в NSInputStream?

Я хотел бы добавить три «части» в NSInputStream: NSString, вывод из другого потока и еще один NSString. Идея заключается в следующем:

Первая и последняя строки NSString представляют собой начало и конец запроса SOAP, в то время как вывод потока является результатом загрузки очень большого файла и его кодирования в виде строки Base64. Итак, в конце концов, я бы хотел, чтобы последний NSInputStream содержал весь запрос SOAP следующим образом:

‹ мыльное начало > ‹ Данные в кодировке Base64 > ‹ мыльное окончание >

Причина, по которой я хочу, чтобы весь запрос хранился в NSInputStream, двояка:

  1. Я не знаю, что загружать очень большой файл данных в память
  2. Я думаю, что это единственный способ принудительно отправить окончательный запрос в виде фрагментов HTTP 1.1 (что мне нужно, потому что иначе, если запрос станет слишком большим, сервер его не примет). Итак, я знаю, что делаю это:

    NSInputStream *dataStream = ....; 
    [request setHTTPBodyStream:dataStream];
    

гарантирует, что запрос будет отправлен как фрагменты HTTP 1.1, а не как один огромный необработанный запрос SOAP.

Итак, мне интересно, как этого можно добиться, а именно, как мне «ставить в очередь» вещи в NSInputStream? Можно ли это сделать? Есть ли альтернативный способ?

Просто для справки, в Java это можно сделать следующим образом

 Vector<InputStream> streamVec = new Vector<InputStream>();
 BufferedInputStream fStream = new BufferedInputStream(fileData.getInputStream());
 Base64InputStream b64stream = new Base64InputStream(fStream, true);
 String[] SOAPBody = GenerateSOAPBody(fileInfo).split("CUT_HERE");  
 streamVec.add(new ByteArrayInputStream(SOAPBody[0].getBytes()));
 streamVec.add(b64stream);
 streamVec.add(new ByteArrayInputStream(SOAPBody[1].getBytes()));
 SequenceInputStream seqStream = new SequenceInputStream(streamVec.elements());

потому что в Java эти объекты доступны, но NSStreams в target-c выглядят как объекты очень низкого уровня, и с ними очень сложно работать.

Примечание. Я полностью переписал исходный вопрос, заданный 2 дня назад, так как я думаю, что новое редактирование более четко объясняет, в чем проблема. Я надеюсь, что это поможет легче понять и, возможно, ответить

ОБНОВЛЕНИЕ 2

Вот чего мне удалось добиться на данный момент: вместо того, чтобы пытаться поставить в очередь поток, я использую временный файл, чтобы сначала записать начало мыла ‹ >, затем я настраиваю входной поток для чтения из файла в чанки, кодирую каждый чанк как строку Base64 и записываю это в тот же временный файл, наконец, когда мой поток закрывается, я записываю мыльное окончание ‹ > во временный файл. Затем я настраиваю другой входной поток с содержимым этого файла, который я передаю в NSMutableURLRequest:

        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
        ...
        NSInputStream *dataStream = [NSInputStream inputStreamWithFileAtPath:_tempFilePath];
        [request setHTTPBodyStream:dataStream];

Это обеспечивает поблочную передачу содержимого файла по HTTP 1.1. После завершения подключения удалите временный файл.

Кажется, это работает нормально, но, конечно, это раздражает. Я не хочу писать во временный файл, когда все это можно было бы обработать потоками (в идеале). Если у кого-то все еще есть лучшие предложения, дайте мне знать :)

ОБНОВЛЕНИЕ 3

Хорошо, еще одно обновление в порядке. Хотя моя запись в файл, кажется, работает, я столкнулся с неожиданной проблемой, когда некоторые из моих запросов не загружаются на сервер. В частности, все идет по плану, я читаю содержимое временного файла в поток и устанавливаю тело HTTP моего запроса в этот поток, и он начинает передавать фрагменты HTTP 1.1, как я хочу, но для некоторых причина, по которой некоторые пакеты отбрасываются, а окончательный запрос — это мое предположение — искажается и, таким образом, терпит неудачу. Я думаю, что проблема с отброшенными пакетами является случайной, потому что я наблюдаю ее на больших запросах, то есть проблема просто имеет больше шансов проявиться, в то время как мои небольшие запросы обычно проходят нормально. Это, конечно, отдельный вопрос от оригинала в этом вопросе. Если у кого-нибудь есть хорошее представление о том, что может быть причиной этого, я спросил о проблеме здесь: Пакеты отброшены во время сегментированного запроса HTTP 1.1, отправленного NSURLConnection


person PeterD    schedule 05.03.2013    source источник


Ответы (1)


Ваше решение - нормальный вариант, но вы можете сделать это с потоком. Это означает создание подкласса NSInputStream, и это не тривиально, потому что вам нужно реализовать множество методов.

По сути, ваш подкласс сначала вернет байты заголовка, затем он вернет байты из «внутреннего» потока в содержимое файла, а затем, когда он будет израсходован, он вернет байты нижнего колонтитула. Это означает ведение записи о том, насколько велики верхний и нижний колонтитулы и сколько уже было обработано, но это не большая проблема.

Здесь приведен пример создания подкласса здесь, который показывает сложную скрытую методы, которые вам необходимо реализовать, чтобы заставить подкласс потока работать правильно, не вызывая исключений.

person Wain    schedule 05.07.2016