Running in NSInputStream?

I would like to add three “parts” to NSInputStream: NSString, exit from another stream, and then another NSString. The idea is this:

The first and last NSStrings represent the beginning and end of the SOAP request, while exiting the stream is the result of loading a very large file and encoding it as Base64 strings. So in the end, I will have the last NSInputStream containing the entire SOAP request as follows:

<soap start> <Base64 encoded data> <soap end>

The reason I want the whole request to be contained in NSInputStream is twofold:

  • I do not need to load a very large data file into memory
  • I think this is the only way to ensure that the final request is sent to HTTP 1.1 hosts (which I need, because otherwise, if the request becomes too large, the server will not accept it). So, I know this does:

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

ensures that the request will be sent as fragments of HTTP 1.1, and not as one huge raw SOAP request.

So, I wonder how this can be achieved - namely, how can I “insert” things into NSInputStream? Can this be done? Is there an alternative way?

Just for reference, in Java this can be done as follows

  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()); 

because Java has these objects, but NSStreams in objective-c look like very low-level objects and it’s very difficult to work with them.

Note. I completely rewrote the original question, as I asked it 2 days ago, since I think the new editing more clearly explains what the problem is. I hope this helps him to better understand and possibly respond.

UPDATE 2

Here's what I managed to achieve: instead of trying to insert into the stream, I use a temporary file to write <soap start> first, then I set up the input stream to read from the file in pieces, encoded each piece as a Base64 string and wrote it to the same temp file, finally, when my thread closes, I write a <soap ends> temporary file. Then, I installed another input stream with the contents of this file, which I pass to NSMutableURLRequest:

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

This ensures that HTTP 1.1 file contents are transferred. After the connection is complete, delete the temporary file.

This seems to work fine, but of course it is annoying work. I do not want to write to a temporary file when all this could be processed by threads (ideally). If anyone else has the best deals let me know :)

UPDATE 3

OK, another update is ok. Although my writing to a file seems to work, now I am facing an unexpected problem when some of my requests are not uploaded to the server. In particular, everything goes according to plan, I read the contents of the temporary file in the stream and set the HTTP body of my request as this stream, and it starts to send HTTP fragments as I want, but for some the reason some packets are dropped and the final request - this is my hunch - gets the wrong form and thus fails. I think that the problem with packaged packages is random, because I observe it with larger requests - that is, the problem just has a better chance of appearing - while my smaller requests usually go through a fine. This, of course, is a separate question from the original in this question. If someone has a good idea what could be causing this, I asked about the problem here: Packets dropped during a chunked HTTP 1.1 request sent by NSURLConnection

+8
ios nsstream nsinputstream
source share
1 answer

Your solution is an ok option, but you can do it with a stream. This means subclassing NSInputStream , and it is not trivial because there are many methods that you need to implement.

Basically, your subclass initially returned the bytes of the header, then it returned the bytes from the "internal" stream to the contents of the file, and then when it used it, it returned the bytes of the footer. This means keeping a record of how large the header and footer are and how many have been processed so far, but this is not a big problem.

Here's an example of creating a subclass here , which shows complex hidden methods that you need to implement in order to make a subclass of a thread work correctly without throwing an exception.

0
source share

All Articles