使用AFNetworking上传多张照片遇到的问题

2018-06-21  本文已影响9人  子非鱼7868

新公司需要上传多张照片,类似于电商的评价图片,上次使用AFNetworking上传图片是两年前了.网上看了一些资料,看到有可以直接拿来用的,我就copy过来了,省心省力,贴上从网上找的代码

## 上传多张图片 
NSArray * _imageArr = @[@"1",@"2",@"3"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 20;
manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"text/plain",@"multipart/form-data"]];
[manager POST:@"http://192.168.0.105:8080/miracle/Upload.action" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
    
    for (int i=0; i<_imageArr.count; i++) {   
    UIImage * image =[UIImage  imageNamed:_imageArr[I]];
    NSDate *date = [NSDate date];
    NSDateFormatter *formormat = [[NSDateFormatter alloc]init];
    [formormat setDateFormat:@"HHmmss"];
    NSString *dateString = [formormat stringFromDate:date];
    NSString *fileName = [NSString  stringWithFormat:@"%@.png",dateString];
    NSData *imageData = UIImageJPEGRepresentation(image, 1);
    double scaleNum = (double)300*1024/imageData.length;
    NSLog(@"图片压缩率:%f",scaleNum);
    if(scaleNum <1){ 
        imageData = UIImageJPEGRepresentation(image, scaleNum);
    }else{    
        imageData = UIImageJPEGRepresentation(image, 0.1);    
    } 
    [formData  appendPartWithFileData:imageData name:@"files" fileName:fileName mimeType:@"image/jpg/png/jpeg"];
    }
} progress:^(NSProgress * _Nonnull uploadProgress) {
    NSLog(@"---%@",uploadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
NSLog(@"`````````%@",responseObject);
NSDictionary *datas = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
    NSLog(@"请求成功%@",datas);   
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  
}];
 

下面是我自己使用的时候的代码

/*
     此段代码如果需要修改,可以调整的位置
     1. 把upload.php改成网站开发人员告知的地址
     2. 把file改成网站开发人员告知的字段名
     */
    NSMutableArray *tempArray = [NSMutableArray array] ;
    NSDictionary *dic = @{@"param1":[NSString stringWithFormat:@"%lld",self.param1],@"param2":[NSString stringWithFormat:@"%lld",self.param2] ,};
    [tempArray addObject:dic];
    NSString * tempString = [self arrayToJSONString:tempArray];
    NSDictionary *dict = @{@"param3":tempString,@"param4":[NSString stringWithFormat:@"%lld",self.param4] };
    
    // 基于AFN3.0+ 封装的HTPPSession句柄
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = 20;
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
    
//formData: 专门用于拼接需要上传的数据,在此位置生成一个要上传的数据体
    [manager POST:URL  parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        // formData: 专门用于拼接需要上传的数据,在此位置生成一个要上传的数据体
        // 这里的_photoArr是你存放图片的数组
        for (int i = 0; i < _photosArr.count; i++) {
            
            UIImage *image = _photosArr[i];
            NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
            // 在网络开发中,上传文件时,是文件不允许被覆盖,文件重名
            // 要解决此问题,
            // 可以在上传时使用当前的系统事件作为文件名
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            // 设置时间格式
            [formatter setDateFormat:@"yyyyMMddHHmmss"];
            NSString *dateString = [formatter stringFromDate:[NSDate date]];
            NSString *fileName = [NSString  stringWithFormat:@"%@%d.jpg", dateString,i];
            /*
             *该方法的参数
             1. appendPartWithFileData:要上传的照片[二进制流]
             2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
             3. fileName:要保存在服务器上的文件名
             4. mimeType:上传的文件的类型
             */
            if (i == 0) {
                [formData appendPartWithFileData:imageData name:@"eReceiptImg" fileName:fileName mimeType:@"image/jpeg"];
            }else{
                [formData appendPartWithFileData:imageData name:[NSString stringWithFormat:@"eReceiptImg%d",i+1] fileName:fileName mimeType:@"image/jpeg"];
            }
            //
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        //上传进度
        // @property int64_t totalUnitCount;     需要下载文件的总大小
        // @property int64_t completedUnitCount; 当前已经下载的大小
        //
        // 给Progress添加监听 KVO
        NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
        // 回到主队列刷新UI,用户自定义的进度条
        dispatch_async(dispatch_get_main_queue(), ^{
//            self.progressView.progress = 1.0 *
//            uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
            [SVProgressHUD showProgress:(1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount) status:@"保存中..."];
            
        });
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        [SVProgressHUD dismiss];
        NSLog(@"```上传成功``` %@",responseObject);
        NSDictionary *dict = (NSDictionary *)responseObject;
        NSInteger inter = [dict[@"success"] integerValue];
        NSString *alertSTR = dict[@"msg"];   
        if (inter == 1) {
            [self.view makeToast:@"保存成功" duration:2 position:CSToastPositionCenter title:nil image:nil style:nil completion:^(BOOL didTap) {
                if ([_delegate respondsToSelector:@selector(signOkClick:)]) {
                    [_delegate signOkClick:self];
                }
                [self.navigationController popViewControllerAnimated:YES];
            }];
            
        }else{
            [self.view makeToast:alertSTR duration:2 position:CSToastPositionCenter];
        }    
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        [SVProgressHUD showErrorWithStatus:@"上传失败"];
        [SVProgressHUD dismissWithDelay:1.5];
    }];

说说我在使用的时候遇到的问题
我上传了,我这边显示上传成功,后台可以收到parameters的参数,但是收不到图片.开始找原因
1.上网看了下资料,说是下面的name不一样,但是确实和后台商量好的,字段没有错.排除这个原因.

Snip20180621_1.png

2.自己断点看了下formData的状态,发现没有下面标的这个NSObject,就想是不是对象被提前释放了,我又看了公司以前的项目,发现他是有的,其他代码基本一样,但是AFNetworking用的是3.0,我用的是3.1.0,我就把我的版本改成3.0,改过之后确实出现了NSObject.具体原因未知但是结果是后台还是收不到

Snip20180621_2.png
3.没办法了,我去找后台的同学联调,联调的结果是后台在收到请求之后就不往下编译了,在解析我上传的parameters停住了,想到了另外一个原因,是不是我上传的参数的格式不对,导致解析不了,造成失败,结果确实是这样,我这边上传的是字典,后台要的是json字符串.通过下面的方法将参数转成json字符串,问题得到解决
注意:这一段就是我改动的地方,有三个参数,需要将两个参数放在字典里然后再放在数组里,最后生成json字符串,在和另外一个一起放字典里上传
    NSMutableArray *tempArray = [NSMutableArray array] ;
    NSDictionary *dic = @{@"param1":[NSString stringWithFormat:@"%lld",self.param1],@"param2":[NSString stringWithFormat:@"%lld",self.param2] ,};
    [tempArray addObject:dic];
    NSString * tempString = [self arrayToJSONString:tempArray];
//dict是请求的参数parameters
    NSDictionary *dict = @{@"param3":tempString,@"param4":[NSString stringWithFormat:@"%lld",self.param4] };
- (NSString *)arrayToJSONString:(NSArray *)array
{
    
    NSError *error = nil;
    //    NSMutableArray *muArray = [NSMutableArray array];
    //    for (NSString *userId in array) {
    //        [muArray addObject:[NSString stringWithFormat:@"\"%@\"", userId]];
    //    }
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    //    NSString *jsonTemp = [jsonString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    //    NSString *jsonResult = [jsonTemp stringByReplacingOccurrencesOfString:@" " withString:@""];
    //    NSLog(@"json array is: %@", jsonResult);
    return jsonString;
}
上一篇 下一篇

猜你喜欢

热点阅读