AFNetworking Multipart Form Requ

作者: Shengsheng0 | 来源:发表于2017-12-17 21:20 被阅读12次

    问题描述

    前不久我在开发公司的一款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工具一片绿...好像哪里不对,怎么就绿了呢😂...

    non-leak.png

    相关文章

      网友评论

        本文标题:AFNetworking Multipart Form Requ

        本文链接:https://www.haomeiwen.com/subject/eoyuwxtx.html