使用 AFNetworking 同时处理数百个请求

Posted

技术标签:

【中文标题】使用 AFNetworking 同时处理数百个请求【英文标题】:Hit hundreds of requests concurrently using AFNetworking 【发布时间】:2016-09-24 18:54:56 【问题描述】:

我需要同时处理数百个请求才能上传文件。我正在使用 AFNetworking,我只是从 for 循环中调用一个方法。但它在某些文件中给了我内部服务器错误。服务器端什么都没有。此过程已从 Web 成功执行。

这是我的代码:

for (UIImage *img in imgages) 
        [self uploadImage:img];
      


-(void) uploadImage:(UIImage *)image




    //    NSDictionary *someData=@x:x 
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:someData
                                                       options:0

                                                         error:nil];

        NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[BASE_URL stringByAppendingString:@"xyz.com"] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) 
        [formData appendPartWithFormData:jsonData name:@"abc"];

        if (imgData) 

            [formData appendPartWithFormData:imgData name:@"file"];

        
     error:nil];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

     NSURLSessionUploadTask *uploadTask;

   manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    uploadTask = [manager
                  uploadTaskWithStreamedRequest:request
                  progress:nil completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) 

                  ];

    [uploadTask resume];


实现上述功能的最佳方式是什么?

【问题讨论】:

您收到的确切错误是什么? ios 有每个主机的并发请求限制,但如果这是您遇到的情况,您将因请求过多而超时。 尝试使用dispatch_apply而不是fo-loop @Vikas 如果它有效,请接受答案 【参考方案1】:

尝试使用以下代码同时上传文件。

 -(id)init 
self = [super init];
if(self) 
    backgroundQueue = dispatch_queue_create("com.bgqueue", NULL);

    dispatch_once(&onceToken, ^

        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.Demo-Upload"];
        sessionConfiguration.HTTPMaximumConnectionsPerHost = 10;
         manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfiguration];
    );

return self;


- (void)processFiles
    for (UIImage *img in imgages) 
         dispatch_async(backgroundQueue, ^(void) 
             [self uploadImage:img];
         );
    



-(void) uploadImage:(UIImage *)image

     // Prepare a temporary file to store the multipart request prior to sending it to the server due to an alleged
     // bug in NSURLSessionTask.
     NSString* tmpFilename = [NSString stringWithFormat:@"%f", [NSDate timeIntervalSinceReferenceDate]];
     NSURL* tmpFileUrl = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tmpFilename]];

     // Create a multipart form request.
     NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[BASE_URL stringByAppendingString:@"xyz.com"] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) 
    [formData appendPartWithFormData:jsonData name:@"abc"];

       if (imgData) 
          [formData appendPartWithFormData:imgData name:@"file"];
       
      error:nil];

     // Dump multipart request into the temporary file.
    [[AFHTTPRequestSerializer serializer] requestWithMultipartFormRequest:request
                                          writingStreamContentsToFile:tmpFileUrl
                                                    completionHandler:^(NSError *error)
     
          // Once the multipart form is serialized into a temporary file, we can initialize
          // the actual HTTP request using session manager.


          // Here note that we are submitting the initial multipart request. We are, however,
          // forcing the body stream to be read from the temporary file.

           self.uploadTask = [manager uploadTaskWithRequest:request
                                fromFile:tmpFileUrl
                                progress:^(NSProgress * _Nonnull uploadProgress)
                                            
                                                NSLog(@"Progress… %f", uploadProgress.fractionCompleted);
                                            
                                completionHandler:^(NSURLResponse *response, id responseObject, NSError *error)
                                           
                                               // Cleanup: remove temporary file.
                                               [[NSFileManager defaultManager] removeItemAtURL:tmpFileUrl error:nil];

                                               // Do something with the result.
                                               if (error)
                                               
                                                 //Print Error
                                                else
                                               
                                                   //Print responseObject
                                               
                                           ];
         // Start the file upload.
         [self.uploadTask resume];
    ];
 

当应用程序进入后台时,上述功能将继续上传图像。因此,这不会给您内部服务器错误或任何超时错误。

希望对您有所帮助。如果您对上述代码有任何疑问,请随时提问。

【讨论】:

以上是关于使用 AFNetworking 同时处理数百个请求的主要内容,如果未能解决你的问题,请参考以下文章

在 Firebase Cloud Messaging 上订阅数百个主题时,iOS 应用程序崩溃

如何在网页中同时传播数百个带有动画和交互式 webgl 上下文的小画布?

如何高效地处理数百个项目中的数千个 C# 文件?

一次将数百个图像绘制到 JFrame 的有效方法是啥?

如果我需要用户可以访问数百个其他用户的数据,我可以使用Realm DB吗?

对数百个网站提出卷曲请求会被某些主机视为攻击吗?