【问题标题】:AFNetworking 2.0 track file upload progressAFNetworking 2.0 跟踪文件上传进度
【发布时间】:2023-03-31 13:31:01
【问题描述】:

我对 AFNetworking 2.0 比较陌生。使用下面的代码 sn-p,我已经能够成功地将照片上传到我的网址。我想跟踪增量上传进度,但我找不到使用 2.0 版执行此操作的示例。我的应用是 iOS 7,所以我选择了 AFHTTPSessionManager。

谁能提供一个示例,说明如何修改此 sn-p 以跟踪上传进度?

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"myimage.jpg"], 1.0);

[manager POST:@"http://myurl.com" parameters:dataToPost constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:imageData name:@"attachment" fileName:@"myimage.jpg" mimeType:@"image/jpeg"];
} success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Success %@", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"Failure %@, %@", error, [task.response description]);
}];

【问题讨论】:

    标签: ios afnetworking-2


    【解决方案1】:

    AFHTTPSession 的接口没有提供设置进度块的方法。相反,您必须执行以下操作:

    // 1. Create `AFHTTPRequestSerializer` which will create your request.
    AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
    
    // 2. Create an `NSMutableURLRequest`.
    NSMutableURLRequest *request =
        [serializer multipartFormRequestWithMethod:@"POST" URLString:@"http://www.myurl.com"
                                        parameters:dataToPost
                         constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                           [formData appendPartWithFileData:imageData
                                                       name:@"attachment"
                                                   fileName:@"myimage.jpg"
                                                   mimeType:@"image/jpeg"];
                         }];
    
    // 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    AFHTTPRequestOperation *operation =
        [manager HTTPRequestOperationWithRequest:request
                                         success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                           NSLog(@"Success %@", responseObject);
                                         } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                           NSLog(@"Failure %@", error.description);
                                         }];
    
    // 4. Set the progress block of the operation.
    [operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                        long long totalBytesWritten,
                                        long long totalBytesExpectedToWrite) {
      NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
    }];
    
    // 5. Begin!
    [operation start];
    

    此外,您不必通过UIImage 读取图像,然后使用JPEG 再次对其进行压缩以获得NSData。只需使用+[NSData dataWithContentsOfFile:] 直接从您的包中读取文件。

    【讨论】:

    • 感谢您的出色回答。但是,setUploadProgressBlock 块没有被调用。上传完成后只调用一次。你能帮我解释一下并解决它吗?
    • 请注意,-multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock: 现已弃用,您可以改用-multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error(有一个额外的错误参数)!
    【解决方案2】:

    AFHTTPSessionManager的接口确实没有提供跟踪上传进度的方法。 但是AFURLSessionManager 可以。

    作为AFURLSessionManager 的继承类AFHTTPSessionManager 可以像这样跟踪上传进度:

    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]  multipartFormRequestWithMethod:@"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:@"uploadFile" fileName:@"image" mimeType:@"image/jpeg"];
    } error:nil];
    
    NSProgress *progress;
    NSURLSessionDataTask *uploadTask = [[AFHTTPSessionManager sharedManager] uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (!error) {
            //handle upload success
        } else {
            //handle upload failure
        }
    }];
    [uploadTask resume];
    [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];
    

    外面

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
            NSProgress *progress = (NSProgress *)object;
            //progress.fractionCompleted tells you the percent in CGFloat
        }
    }
    

    这里是方法2(更新)

    使用KVO 跟踪进度意味着self 在观察期间需要活着。更优雅的方式是AFURLSessionManager的方法setTaskDidSendBodyDataBlock,像这样:

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager setTaskDidSendBodyDataBlock:^(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
        //during the progress
    }];
    
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]  multipartFormRequestWithMethod:@"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:@"uploadFile" fileName:@"image" mimeType:@"image/jpeg"];
    } error:nil];
    
    NSURLSessionDataTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (!error) {
            //handle upload success
        } else {
            //handle upload failure
        }
    }];
    [uploadTask resume];
    

    【讨论】:

    • setTaskDidSendBodyDataBlock 在发送完所有数据后调用。这不是一个循序渐进的过程。如何逐步获得进度百分比?我正在使用 dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
    • 奇怪的是,当它上传完成时,它被多次调用。这可能是一些线程相关的问题
    • 我错过了使用 AFHTTPSessionManager 的 NSURLSessionConfiguration。它逐渐被调用。虽然在 dataTaskWithRequest:uploadProgress:downloadProgress:completi‌​onHandler 中:uploadProgress 完成后仍在被调用。
    • 它似乎也工作正常。我的代码在 dispatch_async(dispatch_get_main_queue(), ^{});块,它在最后被调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2016-05-19
    • 2014-06-03
    • 2013-05-19
    • 1970-01-01
    相关资源
    最近更新 更多