我想向 NSInputStream 添加三个“部分”:一个 NSString,另一个流的输出,然后是另一个 NSString。思路如下:
第一个和最后一个 NSString 表示 SOAP 请求的开始和结束,而流的输出是加载一个非常大的文件并将其编码为 Base64 字符串的结果。所以,最后我会让最终的 NSInputStream 保存整个 SOAP 请求,如下所示:
<soap开头> <Base64编码数据> <soap结尾>
我希望将整个请求保存在 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 有这些对象可用,但是 Objective-c 中的 NSStreams 看起来像非常低级的对象并且很难使用。
注意:我完全重写了两天前提出的原始问题,因为我认为新的编辑更清楚地解释了问题所在。我希望它会帮助它更容易理解并回答
更新 2
到目前为止,这是我能够实现的目标:我没有尝试加入流,而是使用临时文件先写入 <soap beginning>,然后设置输入流以从文件中读取块,将每个块编码为 Base64 字符串并将其写入同一个临时文件,最后,当我的流关闭时,我将 <soap ending> 写入临时文件。然后我用这个文件的内容设置了另一个输入流,我将它传递给 NSMutableURLRequest:
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
...
NSInputStream *dataStream = [NSInputStream inputStreamWithFileAtPath:_tempFilePath];
[request setHTTPBodyStream:dataStream];
这确保了文件内容的 HTTP 1.1 分块传输。连接完成后,删除临时文件。
这似乎工作正常,但当然这是一个烦人的工作。我不想写一个临时文件,因为它本来可以由流处理(理想情况下。)如果有人还有更好的建议,请告诉我:)
更新 3
好的,另一个更新是为了。虽然我的文件写入似乎有效,但我现在遇到了一个意外问题,我的一些请求无法上传到服务器。具体来说,一切都按计划进行,我正在将临时文件的内容读入一个流,并将我的请求的 HTTP 主体设置为这个流,它开始按照我的意愿传输 HTTP 1.1 块 - 但对于一些一些数据包被丢弃并且最终请求 - 这是我的猜测 - 格式错误并因此失败的原因。我认为丢弃数据包的问题是随机的,因为我在较大的请求中观察到它 - 也就是说,这个问题有更多的机会出现 - 而我的较小的请求通常会很好。这当然是与该问题中的原始问题不同的问题。如果有人知道可能导致这种情况的原因,在 NSURLConnection 发送的分块 HTTP 1.1 请求期间丢弃的数据包