Ставить в очередь в NSInputStream?
Я хотел бы добавить три "части" к NSInputStream: NSString, вывод из другого потока и затем еще одну NSString. Идея заключается в следующем:
Первая и последняя строки NSString представляют начало и конец запроса SOAP, в то время как выходные данные из потока являются результатом загрузки очень большого файла и кодирования его в виде строки Base64. Итак, в конце я бы хотел, чтобы последний NSInputStream содержал весь SOAP-запрос следующим образом:
<мыло начало> <данные, закодированные в Base64> <мыло конец>
Причина, по которой я хочу, чтобы весь запрос содержался в NSInputStream, имеет две причины:
- Мне не то, что загрузить очень большой файл данных в память
Я думаю, что это единственный способ принудительно отправить окончательный запрос в порциях 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
1 ответ
Ваше решение - хороший вариант, но вы можете сделать это с помощью потока. Это означает, что подкласс NSInputStream
и это не тривиально, потому что есть множество методов, которые нужно реализовать.
По сути, ваш подкласс первоначально будет возвращать байты заголовка, затем он будет возвращать байты из "внутреннего" потока в содержимое файла, затем, когда он израсходован, он возвращает байты нижнего колонтитула. Это означает ведение записи о том, насколько велики заголовок и нижний колонтитул и сколько было обработано до сих пор, но это не является большой проблемой.
Здесь есть пример создания подкласса, который показывает хитрые скрытые методы, которые вам нужно реализовать, чтобы заставить потоковый подкласс работать должным образом, не вызывая исключения.