Python iOS分块上传

Python iOS分块上传,python,ios,objective-c,http,pyramid,Python,Ios,Objective C,Http,Pyramid,我正在尝试将联系人从用户的通讯簿流式传输到我们的服务器。一次将所有触点拉入内存可能会导致设备崩溃或无响应。我不想承担将所有联系人写入文件并上载文件的开销。我可以看到数据是通过电线发送的,但看起来格式无效。服务器无法识别请求正文 我正在从通讯簿中读取联系人并将其写入NSOutputStream。此NSOutputStream通过以下代码与NSInputStream共享缓冲区 然后,网络请求像这样出现:(使用Wireshark捕获) 我不确定为什么9BD和0包含在请求正文中。我认为这是缓冲区设置的

我正在尝试将联系人从用户的通讯簿流式传输到我们的服务器。一次将所有触点拉入内存可能会导致设备崩溃或无响应。我不想承担将所有联系人写入文件并上载文件的开销。我可以看到数据是通过电线发送的,但看起来格式无效。服务器无法识别请求正文

我正在从通讯簿中读取联系人并将其写入NSOutputStream。此NSOutputStream通过以下代码与NSInputStream共享缓冲区

然后,网络请求像这样出现:(使用Wireshark捕获)

我不确定为什么9BD和0包含在请求正文中。我认为这是缓冲区设置的错误,我相信这会导致服务器忽略http主体,因为它是无效的。看起来我正确地构建了请求吗?有更好的方法吗?我正在使用pyramid/python来处理请求。服务器接收到的请求正常,但请求正文为空

编辑 如果我不发送任何联系人,“9BD”就会消失。如果我更改联系人数据,“9BD”将更改为不同的字符。“0”始终位于底部

编辑2
吉姆指出请求的格式是有效的。这意味着服务器没有正确处理流。请求命中服务器正常,服务器回复正常。但是,我没有看到任何请求主体。服务器正在运行pyramid/python。在服务器上,request.body为空。

该请求没有问题。您的请求已分块:

Transfer-Encoding: Chunked
9BD
指示下一个块的长度。末尾的零表示没有更多的块

有关详细信息,请参阅


您的问题可能是服务器不理解分块请求。

您的流处理程序委托不正确:

在这里,当您将数据写入producerStream时:

[self.producerStream write:[data bytes] maxLength:[data length]];
可能发生的情况是,
NSData
对象中的所有字节都无法写入流中。当这种情况发生时,您会丢失字节

要解决此问题,需要检查
write:maxLength:
的返回值,该值等于写入的字节数(或指示错误)。然后,您需要保存
NSData
对象的状态以及从该数据对象写入流的字节范围。在下一个事件循环中,您需要检查数据是否还有字节,并继续写入字节,直到写入所有字节

实际上,这类任务的健壮实现非常棘手,而且容易出错

我想分享一些代码,这些代码将一个流复制到另一个流,并且已经过测试:

此代码可能会让您快速启动。类
RXStreamToStreamCopier
将源流复制到目标流中。流在运行循环上调度,您可以指定该循环。该类类似于
NSOperation
,可以启动和取消

在内部,该类使用一个固定大小的传输缓冲区和一个
pull
方法从源流读取,并使用
push
方法写入目标流。您可以覆盖
push
方法来转换源字节

使用创建
RXStreamToStreamCopier
对象

- (id) initWithSourceStream:(NSInputStream*)sourceStream
          destinationStream:(NSOutputStream*)destinationStream;
源流将与您的数据源相关联。目标流通常是有界流对的一半。然后,可以通过请求的属性
HTTPBodyStream
最终设置有界流对的另一端(输入流)

您可以按原样使用它,但它取决于另一个库

使用分块传输编码的解决方法提示: 如果您事先知道流字节的大小,则可以显式设置内容长度标头。这将导致
NSURLConnection
不使用分块传输编码


正如@Rob在评论中所述,
NSURLSession
的行为将有所不同:如果将流设置为输入,则将删除内容长度头,这将导致分块传输编码。

一旦我弄清楚如何配置服务器以接受分块请求,我将告诉您结果。另外,我有C标记,因为大部分缓冲区代码都是用C编写的。我一直在做其他事情,没有时间重新讨论这个问题。这么说,赏金就要到期了。享受赏金吧,我会让你知道你的解决方案是如何运作的。@Rob谢谢你的评论。实际上,我没有针对这种特定行为测试NSURLSession。再次感谢您的更正。
POST /upload?token=dd224bceb02929b36d35&agent=iPhone%20Simulator&v=1.0 HTTP/1.1
Host: localhost:6547
Transfer-Encoding: Chunked
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=UTF-8
Accept-Language: en-us
Connection: keep-alive
Accept: */*
User-Agent: MyApp/2.0 CFNetwork/672.0.8 Darwin/13.0.0

9BD



{"contacts": [(valid json array)]}



0
Transfer-Encoding: Chunked
[self.producerStream write:[data bytes] maxLength:[data length]];
- (id) initWithSourceStream:(NSInputStream*)sourceStream
          destinationStream:(NSOutputStream*)destinationStream;