安路的技术博客

Nothing in life is to be feared. It is only to be understood

利用AFNetworking上传图片和视频

| Comments

前言

之前尝试过用原生的上传代码,但是比较麻烦,利用afnetworking进行上传还是很方便的。

文件上传后台服务器必须要有相应的代码支持,我们后台使用java做的,首先ios客户端要把上传的图片或者视频转换成标准的文件流,然后传给后台,才能顺利实现上传功能。

上传图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
 *  上传图片
 */
-(void)uploadPicture:(UIImage *)selectImg{
    //房源id:houseId 经纪人姓名:agentName flag(0未审核)文件:file
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:URL_UPLOADFILES parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
                                    {
                                        NSData *imgData=UIImageJPEGRepresentation(selectImg, 1.0);
                                        [formData appendPartWithFileData:imgData name:@"file" fileName:@"ios.png" mimeType:@"image/jpeg"];
                                        
                                        NSData *data =[@"654321" dataUsingEncoding:NSUTF8StringEncoding];

                                        [formData appendPartWithFormData:data name:@"houseAppKey"];
                                        
                                        NSData *data1 =[_houseID dataUsingEncoding:NSUTF8StringEncoding];
                                        [formData appendPartWithFormData:data1 name:@"houseId"];
                                        
                                    }];
    
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURLSessionUploadTask *uploadTask;
    
    uploadTask = [manager
                  uploadTaskWithStreamedRequest:request
                  progress:nil
                  completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                      [[UIManager shareInstance] hide];
                      if (error) {
                          MYLog(@"Error: %@", error);
                      } else {
                          NSDictionary *dict=responseObject;
                          if(dict){
                              NSInteger result=[dict[@"code"] integerValue];
                              if(result==0){
                                  NSString *msg=dict[@"msg"];
                                  [[UIManager shareInstance] showSuccessWithMessage:msg duration:DURATIONTIME];
                              }else{
                                  [[UIManager shareInstance] showErrorWithMessage:@"上传失败" duration:DURATIONTIME];
                              }
                          }
                      }
                  }];
    [uploadTask resume];
}

上传视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#pragma mark
#pragma mark 上传视频
-(void)updateVedio:(NSData *)vedioData{
    
    
    //房源id:houseId 经纪人姓名:agentName flag(0未审核)文件:file
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:URL_UPLOADFILES parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
                                    {
                                    
                                       [formData appendPartWithFileData:vedioData name:@"video1" fileName:@"video1.mov" mimeType:@"video/quicktime"];
                                        
                                        NSData *data =[@"654321" dataUsingEncoding:NSUTF8StringEncoding];
                                        
                                        [formData appendPartWithFormData:data name:@"houseAppKey"];
                                        
                                        NSData *data1 =[_houseID dataUsingEncoding:NSUTF8StringEncoding];
                                        [formData appendPartWithFormData:data1 name:@"houseId"];
                                        
                                    }];
    
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURLSessionUploadTask *uploadTask;
    
    uploadTask = [manager
                  uploadTaskWithStreamedRequest:request
                  progress:nil
                  completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                      [[UIManager shareInstance] hide];
                      if (error) {
                          MYLog(@"Error: %@", error);
                      } else {
                          NSDictionary *dict=responseObject;
                          if(dict){
                              NSInteger result=[dict[@"code"] integerValue];
                              if(result==0){
                                  NSString *msg=dict[@"msg"];
                                  [[UIManager shareInstance] showSuccessWithMessage:msg duration:DURATIONTIME];
                              }else{
                                  [[UIManager shareInstance] showErrorWithMessage:@"上传失败" duration:DURATIONTIME];
                              }
                          }
                      }
                  }];
    [uploadTask resume];
}

图片多选

如果想要一次上传多张图片的话,可能会用到 AssetsPickerController
这个第三方库

我在代码中用法如下:

 -(void)takeVedios:(UIButton *)btn{
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){
        dispatch_async(dispatch_get_main_queue(), ^{

            // init picker
            CTAssetsPickerController *picker = [[CTAssetsPickerController alloc] init];
            // set delegate
            picker.delegate = self;
            // Optionally present picker as a form sheet on iPad
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
                picker.modalPresentationStyle = UIModalPresentationFormSheet;

            // present picker
            [self presentViewController:picker animated:YES completion:nil];
        });
    }];
}

补充

上传的时候最好有进度条进行提示,这是比较好的用户体验,AFNetworking官方也给出了上传下载的进度条实例,我这块之前没有做出很好的效果,以后有时间了再研究一下。

我用的AF的版本号是2.6的可能和最新版本的AF上传的代码有点区别,进度条的展示可能也有点区别,AFNetworking中的进度条用了NSProcess来显示,NSProcess可以用 KVO来监控实现,

代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
 *  上传临时图片到服务器
 *
 *  @param selectImg 要传入的图片
 *  @param callback  回调函数
 */
-(void)uploadToServerTEMP:(UIImage *)selectImg
      UploadTEMPFileBlock:(UploadTEMPFileBlock)callback{
    
    
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:URL_UPLOADTEMP parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
                                    {
                                        NSData *imgData=UIImageJPEGRepresentation(selectImg, 1.0);
                                        [formData appendPartWithFileData:imgData name:@"Filedata" fileName:@"ios.png" mimeType:@"image/jpeg"];
                                    }];
    
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURLSessionUploadTask *uploadTask;
    
    NSProgress *progress = nil;
    
    uploadTask = [manager
                  uploadTaskWithStreamedRequest:request
                  progress:&progress
                  completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                      if (error) {
                          MYLog(@"Error: %@", error);
                          callback(nil,error);
                      } else {
                          NSDictionary *dict=responseObject;
                          if(dict){
                              callback(dict,nil);
                          }
                          //[progress removeObserver:self forKeyPath:@"fractionCompleted"];
                      }
                  }];
    
    [progress addObserver:self
               forKeyPath:@"fractionCompleted"
                  options:NSKeyValueObservingOptionNew
                  context:NULL];
    [uploadTask resume];
    
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    //[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    
    if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
        NSProgress *progress = (NSProgress *)object;
        NSLog(@"Progress is %f", progress.fractionCompleted);
      
        [_processView setProgress:progress.fractionCompleted animated:YES];
        
         NSLog(@"progress.totalUnitCount:%lld;progress.completedUnitCount=%lld",progress.totalUnitCount,progress.completedUnitCount);
    }
}

经过检验,进度条显示有点问题,可能不是实时显示,进度条显示的不太准确。需要后期优化。

Comments