AFNetworking Multipart Form Request内存泄漏问题

2018-02-09 12:46:53来源:https://www.jianshu.com/p/f5a6d5ff20e7作者:Shengsheng0人点击

分享


问题描述

前不久我在开发公司的一款SDK的过程中,遇到过发生在AFNetworking使用multipart form request来上传文件的内存泄漏问题,调试了半天,后来终于发现问题在于用AFHTTPRequestSerializermultipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:方法来构建multipart form request,会产生内存泄漏。基本上泄露内存的大小,跟上传文件的大小差不多,我没有深入AFHTTPRequestSerializer的源码,具体原因我不清楚,Google也没搜到类似的情况。




leak.png

说明: 截图中的类名都以AS开头,因为这是SDK开发,我直接将AFNetworking的源码放在了SDK项目里面,然后给AFNetworking的类前缀加上了AS从而变成了ASAFNetworking,这样是为了避免集成了SDK的app同时也在用AFNetworking,从而产生类冲突。后期会考虑砍掉AFNetworking,自己基于NSURLSession写一套HTTP框架。
解决方案

之后我把用AFHTTPRequestSerializer构造multipart form request的代码,用原生的方式取代,内存泄露问题解决。整个构造multipart form request的代码用了Stack Overflow上搜的一段代码,代码如下:


// configure the request
NSURL *url = @"https://api-url";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *boundary = [self generateBoundaryString];
// set content type
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// create body
NSString *filePath = @"file-path";
NSData *httpBody = [self createBodyWithBoundary:boundary parameters:nil paths:@[filePath] fieldName:@"file"];
request.HTTPBody = httpBody;

上述代码中用到的两个方法:


- (NSData *)createBodyWithBoundary:(NSString *)boundary
parameters:(NSDictionary *)parameters
paths:(NSArray *)paths
fieldName:(NSString *)fieldName {
NSMutableData *httpBody = [NSMutableData data];
// add params (all params are strings)
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
[httpBody appendData:[[NSString stringWithFormat:@"--%@/r/n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=/"%@/"/r/n/r/n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"%@/r/n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
}];
// add image data
for (NSString *path in paths) {
NSString *filename = [path lastPathComponent];
NSData *data = [NSData dataWithContentsOfFile:path];
NSString *mimetype = [self mimeTypeForPath:path];
[httpBody appendData:[[NSString stringWithFormat:@"--%@/r/n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=/"%@/"; filename=/"%@/"/r/n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@/r/n/r/n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:data];
[httpBody appendData:[@"/r/n" dataUsingEncoding:NSUTF8StringEncoding]];
}
[httpBody appendData:[[NSString stringWithFormat:@"--%@--/r/n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
return httpBody;
}
- (NSString *)generateBoundaryString {
return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
}

最后leak工具一片绿...好像哪里不对,怎么就绿了呢

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台