简体   繁体   English

入队到NSInputStream?

[英]Enqueueing into NSInputStream?

I would like to add three "parts" to an NSInputStream: an NSString, an output from another stream and then another NSString. 我想在NSInputStream中添加三个“部分”:NSString,另一个流的输出,然后是另一个NSString。 The idea is the following: 这个想法如下:

The first and last NSStrings represent the beginning and end of a SOAP request while the output from the stream is a result of loading a very large file and encoding it as Base64 string. 第一个和最后一个NSStrings表示SOAP请求的开始和结束,而流的输出是加载非常大的文件并将其编码为Base64字符串的结果。 So, in the end I would have the final NSInputStream hold the whole SOAP request like this: 所以,最后我会让最终的NSInputStream像这样保存整个SOAP请求:

< soap beginning > < Base64 encoded data > < soap ending > <soap beginning> <Base64编码数据> <soap结束>

The reason I want the whole request to be held in NSInputStream is two-fold: 我希望整个请求保存在NSInputStream中的原因有两个:

  1. I don't what to load the very large data file into memory 我不知道如何将非常大的数据文件加载到内存中
  2. I think that this is the only way to enforce sending the final request in HTTP 1.1 chunks (which I need because otherwise, if the request becomes too big, the server won't accept it). 我认为这是强制在HTTP 1.1块中发送最终请求的唯一方法(我需要它,否则,如果请求变得太大,服务器将不接受它)。 So, I know that doing this: 所以,我知道这样做:

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

ensures that the request will be sent as HTTP 1.1 chunks and not as one huge raw SOAP request. 确保请求将作为HTTP 1.1块发送,而不是作为一个巨大的原始SOAP请求发送。

So, I wonder how this can be achieved - namely, how do I "enqueue" things into an NSInputStream? 所以,我想知道如何实现这一点 - 即,我如何将事物“排入”NSInputStream? Can it be even done? 甚至可以做到吗? Is there an alternative way? 还有另一种方法吗?

Just for reference, in Java this can be done as follows 仅供参考,在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());

because Java has these objects available, but NSStreams in objective-c look like very low level objects and are very hard to work with. 因为Java有这些对象可用,但Objective-c中的NSStreams看起来像非常低级别的对象,并且很难使用。

Note: I completely re-wrote the original question as I asked it 2 days ago, since I think the new edit explains more clearly what the problem is. 注意:我完全重写了原始问题,因为我在2天前问过它,因为我认为新编辑更清楚地解释了问题所在。 I hope it would help it be easier comprehended and maybe answered 我希望这将有助于它更容易理解,也许可以回答

UPDATE 2 更新2

Here is what I've been able to achieve so far: Instead of trying to enqueue into a stream, I am using a temp file to first write the < soap beginning >, then I set up an input stream to read from the file in chunks, encode each chunk as a Base64 string and write this to the same temp file, finally, when my stream closes, I write the < soap ending > to the temp file. 以下是我迄今为止所能实现的目标:我使用临时文件首先编写<soap beginning>,然后设置输入流来从文件中读取,而不是尝试排入流中。块,将每个块编码为Base64字符串并将其写入相同的临时文件,最后,当我的流关闭时,我将<soap ending>写入临时文件。 Then I set up another input stream with the contents of this file which I pass to the NSMutableURLRequest: 然后我设置另一个输入流与该文件的内容,我传递给NSMutableURLRequest:

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

This ensures HTTP 1.1 chunked transfer of the contents of the file. 这确保了HTTP 1.1分块传输文件的内容。 After the connection finishes, delete the temp file. 连接完成后,删除临时文件。

This seems to work fine but of course this is an annoying work-about. 这似乎工作正常,但当然这是一个烦人的工作。 I don't want to be writing to a temp file when it all could have been handled by streams (ideally.) If anybody still has better suggestions, let me know :) 我不想写一个临时文件,当它可以由流处理(理想情况下)。如果有人仍有更​​好的建议,请告诉我:)

UPDATE 3 更新3

OK, another update is in order. 好的,另一个更新是有序的。 While my writing to file seems to work, I am now hitting an unexpected issue with some of my requests failing to upload to the server. 虽然我的文件写入似乎有效,但我现在遇到了一些意外问题,我的一些请求无法上传到服务器。 Specifically, everything is going according to the plan, I am reading the contents of the temp file into a stream and set HTTP body of my request to be this stream and it starts transmitting the HTTP 1.1 chunks as I want it to - but for some reason some packets get dropped and the final request - this is my guess - gets malformed and thus fails. 具体来说,一切都按照计划进行,我正在将临时文件的内容读入流中,并将我的请求的HTTP主体设置为此流,并开始按我的意愿传输HTTP 1.1块 - 但对于某些一些数据包丢失的原因和最后的请求 - 这是我的猜测 - 变得格格不入,因此失败。 I think the issue of dropped packets is random, because I observe it on larger requests - that is, the issue just has more chance to show up - while my smaller requests usually go thru just fine. 我认为丢弃数据包的问题是随机的,因为我在更大的请求上观察它 - 也就是说,问题只是有更多机会出现 - 而我的较小请求通常会很好。 This is of course a separate issue from the original in this question. 这当然是与此问题中的原始问题不同的问题。 If anybody has a good idea what might be causing this, I asked about the problem here: Packets dropped during chunked HTTP 1.1 request sent by NSURLConnection 如果有人知道可能导致这种情况的原因,我在这里询问了问题: 在NSURLConnection发送的分块HTTP 1.1请求期间丢弃了数据包

Your solution is an ok option, but you can do it with a stream. 您的解决方案是一个正常的选择,但您可以使用流来完成。 It means subclassing NSInputStream , and that isn't trivial because there are a bunch of methods you need to implement. 它意味着NSInputStream ,这不是一件容易的事,因为你需要实现一堆方法。

Basically your subclass would initially return the header bytes, then it would return bytes from the 'internal' stream to the file content, then when that's used up it returns the footer bytes. 基本上你的子类最初将返回头字节,然后它会将“内部”流中的字节返回到文件内容,然后当它用完时它会返回页脚字节。 It means maintaining a record of how big the header and footer are and how much has been processed so far, but that isn't a big issue. 这意味着要保留页眉和页脚有多大以及到目前为止处理了多少的记录,但这不是一个大问题。

There's an example of creating a subclass here which shows the tricky hidden methods you need to implement to get the stream subclass to work properly without throwing exceptions. 有创建一个子类的实例在这里这表明你需要实现以获得流子类没有抛出异常正常工作棘手的隐藏方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM