我知道这个问题在本网站上非常流行,但在搜索了大部分答案之后,我找不到解决方案。
我的应用是将图像上传到远程网址。我尝试了几种上传方式,并且所有方法都成功了:
(1)使用AFURLSessionManager
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[(AFHTTPResponseSerializer*)manager.responseSerializer setAcceptableContentTypes:[NSSet setWithObjects:@"multipart/form-data", nil]];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSDictionary *userInfo=[error userInfo];
id responseError=[userInfo objectForKey:@"AFNetworkingOperationFailingURLResponseErrorKey"];
if ([responseError isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *reponse=(NSHTTPURLResponse*)responseError;
if (reponse.statusCode==200) {
result(YES);
} else {
result(NO);
}
} else {
result(NO);
}
} else {
result(YES);
}
}];
[uploadTask resume];
通过这种方式,我使用KVO来监控进度,但没有运气。
(2)使用AFHTTPRequestOperation
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(@"total bytes written: %lld",totalBytesWritten);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
result(YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (operation.response.statusCode==200) {
result(YES);
} else {
result(NO);
}
}];
[operation start];
在开始上传时,它只显示日志“写入的总字节数:”,只显示100%的文件卷。
(3)使用AFHTTPRequestOperationManager
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success %@", responseObject);
result(YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (operation.response.statusCode==200) {
result(YES);
} else {
result(NO);
}
}];
// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
long long totalBytesWritten,
long long totalBytesExpectedToWrite) {
double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
NSLog(@"progress updated(percentDone) : %f", percentDone);
}];
// 5. Begin!
[operation start];
=>与第二种解决方案相同的结果。
请注意,所有解决方案都会成功上传,但进度未更新(NSProgress
或阻止)。
答案 0 :(得分:1)
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"<your upload url>" parameters:@{<parameters dict> } constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
_STRONGREF(strongSelf);
NSString *name=@"file_data_name";
[formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:name fileName:<file Path> mimeType:@"image/png" error:nil];//u can use data as well with other method
}
} error:nil];
[request setTimeoutInterval:180];
[request setValue:@"VAlue_your" forHTTPHeaderField:@"feild"];//set headers
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSProgress *progress = nil;
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
NSLog(@"%@",progress);
[uploadTask resume];
我的宏
#define _WEAKREF(obj) __weak typeof(obj)ref=obj;
#define _STRONGREF(name) __strong typeof(ref)name=ref;\
if(!name)return ;\
答案 1 :(得分:0)
在NSProgress上设置一个观察者。
像
这样的东西[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"]) {
NSProgress *progress = (NSProgress *)object;
NSLog(@"progress = %f", progress.fractionCompleted);
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
上传任务完成后,不要忘记删除观察者。
注意:progress.fractionCompleted返回百分比值。例如,你可以用MB来计算它。
答案 2 :(得分:0)
最后,我发现了没有调用进度块的原因:我已经上传了一张大约几十Kb的非常小的图像。我尝试上传更大的文件并调用进度块。根据我的经验,KVO与NSProgress并不起作用。而不是那样,我们可以使用AFHTTPRequestOperation或AFHTTPRequestOperationManager。如果您更喜欢手动上传,可以按照How can I upload a photo to a server with the iPhone?的建议和委托方法使用NSURLConnection:
- (void)connection:(NSURLConnection *)connection
didSendBodyData:(NSInteger)bytesWritten
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
NSLog(@"percent: %d",100*totalBytesWritten/totalBytesExpectedToWrite);
}