GRKInputStreamAggregate
一个从其他输入的串联序列中读取的流聚合器。使用此功能将多个输入流(和数据块)合并为一条。当上传多部分 MIME 主体时非常有用。
安装
如果您正在使用 CocoPods,则可以将此添加到您的 Podfile
pod 'GRKInputStreamAggregate'
否则,只需将 GRKInputStreamAggregate
子目录的内容添加到您的项目中。
文档
例如,可以使用聚合器提供一个用于多部分文件上传的串联流。
为此,可以通过 NSURLSession
的 uploadTaskWithStreamedRequest:
方法创建一个 NSURLSessionUploadTask
。
示例
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:@"POST"];
[urlRequest setValue: [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
//NOTE: We must pass `[NSOperationQueue mainQueue]` as the `delegateQueue`
NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithStreamedRequest:urlRequest];
然后,实现任务代理方法 URLSession:task:needNewBodyStream:
。
示例
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
{
NSString *fileName = [self.fileURL lastPathComponent];
//Ensure any previous aggregate gets closed
[self.aggregate close];
//Create a new aggregate for the body stream
GRKInputStreamAggregate *aggregate = [[GRKInputStreamAggregate alloc] init];
//Build our body stream by aggregating the multipart boundaries with our file.
[aggregate addString:[NSString stringWithFormat:@"--%@\r\n", kMultipartFormBoundary]];
[aggregate addString:[NSString stringWithFormat: @"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n\r\n", kMultipartFormFileInput, fileName]];
[aggregate addFileURL:self.fileURL];
[aggregate addString:[NSString stringWithFormat:@"\r\n--%@--\r\n", kMultipartFormBoundary]];
self.aggregate = aggregate;
NSInputStream *inputStream = [aggregate openForInputStream];
completionHandler(inputStream);
}
...并在 URLSession:task:didCompleteWithError:
代理方法中确保关闭聚合器。
示例
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
//Ensure any previous aggregate gets closed
[self.aggregate close];
}
作为一条重要的备注,创建您的NSURLSession
时,必须将[NSOperationQueue mainQueue]
作为delegateQueue
传入。这是因为GRKInputStreamAggregate
在内部使用NSStream
,而那些必须与一个活动运行循环相关联。利用来自CFStream.h
的CFWriteStreamSetDispatchQueue
方法来替换运行循环集成可能是有可能的,但是迄今为止,我在不引入竞争条件或死锁的情况下使它工作还未成功。欢迎提交拉取请求... ;)
免责声明和许可
- 这个衍生作品基于来自Couchbase Lite iOS项目的工作,特别是Couchbase的Jens Alfke创建的
CBLMultiStreamWriter
类。Couchbase和Jens Alfke都不支持我(Levi Brown)或这个衍生作品。请参阅许可文件./GRKInputStreamAggregate/LICENSE.txt
- 本作品使用Apache许可证,版本2.0。请参阅包含的LICENSE.txt以获取详细信息。
关于
我是一名职业iOS工程师,我的名字叫Levi Brown。我写了一个博客grokin.gs,您可以通过以下方式联系我
Twitter @levigroker
Email [email protected]
欢迎您提出建设性的评论和反馈。