AFN表单上传图片


AFN表单上传图片

今天在做项目上传图片的时候,用到了formData上传图片,遇到了问题,很奇怪的问题。需求是这样的:
上传图片,首先压缩一定的比例,然后转成base64格式的data,传给后台参数是这样的:img_base64:imageData

  • 在postMan中的请求是这样的:
    postman截图

  • 在代码中,我们需要这样做,图片转码代码如下:

 // 压缩图片质量
 NSData *data = UIImageJPEGRepresentation(img, 0.5);
 // 图片转码
 NSData *dataImg = [data base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];  
  • 算了,直接撸代码
// 1、创建请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
mgr.requestSerializer = [AFHTTPRequestSerializer serializer];

AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:YES];
[mgr setSecurityPolicy:securityPolicy];
[mgr.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[mgr.requestSerializer willChangeValueForKey:@"timeoutInterval"];
mgr.requestSerializer.timeoutInterval = 15.0f; // 默认超时时长为60s
[mgr.requestSerializer didChangeValueForKey:@"timeoutInterval"];
mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
[mgr POST:URL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
// 参数名:img_base64 :dataImg
[formData appendPartWithFormData:dataImg name:@"img_base64"];
} progress:^(NSProgress * _Nonnull uploadProgress) {

} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
    self.responseObj = dict;
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    [mgr.operationQueue cancelAllOperations];
    SHOWERROR(@"识别失败");
}];

注意:在iOS转成base64的data的时候,是不带data:image/png;base64,这个头的,但是安卓在进行这些的时候是有的,所以需要跟后台商量好,踩坑了,以此谨记!
在AFN中还有另一种拼接方式,也是很常见的上传拼接方式

第二种方式


/**
POST请求(接收JSON格式数据)

@param URLString  请求的URL
@param parameters 请求的参数
@param photos 上传图片数组
@param success    请求成功的回调
@param failure    请求失败的回调
*/
- (void)POST:(NSString *)URLString parameters:(id)parameters photos:(NSArray *)photos  success:(void (^)(id responseObject)) success failure:(void(^)(NSError *error)) failure {
   
   // 1、创建请求管理者
   AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
   mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
   mgr.requestSerializer = [AFHTTPRequestSerializer serializer];
   
   AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
   [securityPolicy setAllowInvalidCertificates:YES];
   [mgr setSecurityPolicy:securityPolicy];
   [mgr.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
   
   [mgr.requestSerializer willChangeValueForKey:@"timeoutInterval"];
   mgr.requestSerializer.timeoutInterval = 15.0f; // 默认超时时长为60s
   [mgr.requestSerializer didChangeValueForKey:@"timeoutInterval"];
   
   mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", nil];
   [mgr POST:URLString  parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
       // formData: 专门用于拼接需要上传的数据,在此位置生成一个要上传的数据体
       // 这里的_photoArr是你存放图片的数组
       // formData: 专门用于拼接需要上传的数据,在此位置生成一个要上传的数据体
       // 这里的_photoArr是你存放图片的数组
       for (int i = 0; i < photos.count; i++) {
           
           UIImage *image = photos[i];
           //QFLog(@"+++++%@",image);
           NSData *imageData = UIImagePNGRepresentation(image);
           
           // 在网络开发中,上传文件时,是文件不允许被覆盖,文件重名
           // 要解决此问题,
           // 可以在上传时使用当前的系统事件作为文件名
           NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
           // 设置时间格式
           [formatter setDateFormat:@"yyyyMMddHHmmss"];
           NSString *dateString = [formatter stringFromDate:[NSDate date]];
           NSString *fileName = [NSString  stringWithFormat:@"%@%ld.png", dateString,(NSInteger)i];
           /*
            *该方法的参数
            1. appendPartWithFileData:要上传的照片[二进制流]
            2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
            3. fileName:要保存在服务器上的文件名
            4. mimeType:上传的文件的类型
            */
           [formData appendPartWithFileData:imageData name:@"file" fileName:fileName mimeType:@"application/octet-stream"]; //
       }
   } progress:^(NSProgress * _Nonnull uploadProgress) {
   } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       if (success) {
           success(responseObject);
       }
       [mgr.operationQueue cancelAllOperations];
       
   } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       
       if (failure) {
           failure(error);
       }
       
       [mgr.operationQueue cancelAllOperations];
   }];
}

系统方式

如果不用AFN的话,用系统的方法,就有点麻烦了,这里是系统的方法:

#pragma mark ------系统上传

- (void)uploadHeadImage:(UIImage *)image onSuccess:(void (^)(NSDictionary *dict))onSuccess onFailure:(void(^)(NSError *error))onFailure {
 
//BaseWebAddr:服务器地址
    NSString *urlStr = @"http://47.104.193.88:8080/plant/recognize";
    NSURL *url = [NSURL URLWithString:urlStr];
  
    //在此声明一个字符串常量,代替下面的 BOUNDARY 字符串
//   NSString * const POST_BOUNDS = @"----iOSKitFormBoundarycIO0B6mmsXU6koBg";
    
    NSData *imageData;
    NSString *imageFormat;
    if (UIImagePNGRepresentation(image) != nil) {
        imageFormat = @"Content-Type: image/png \r\n";
        imageData = UIImagePNGRepresentation(image);
        imageData = [imageData base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
        
    }else{
        imageFormat = @"Content-Type: image/jpeg \r\n";
        imageData = UIImageJPEGRepresentation(image, 1.0);
        imageData = [imageData base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
    }
    
    NSMutableURLRequest *request  = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    
    
    //设置请求实体
    NSMutableData *body = [NSMutableData data];
    ///文件参数
    [body appendData:[self getDataWithString:@"--BOUNDARY\r\n" ]];
    NSString *disposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"pppp.jpg\"\r\n",@"img_base64"];
    [body appendData:[self getDataWithString:disposition]];
    [body appendData:[self getDataWithString:imageFormat]];
    [body appendData:[self getDataWithString:@"\r\n"]];
    [body appendData:imageData];
    [body appendData:[self getDataWithString:@"\r\n"]];
    
    //普通参数
    [body appendData:[self getDataWithString:@"--BOUNDARY\r\n" ]];
    //上传参数需要key
    NSString *dispositions = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n",@"uid"];
    [body appendData:[self getDataWithString:dispositions]];
    [body appendData:[self getDataWithString:@"\r\n"]];
    [body appendData:[self getDataWithString:@"\r\n"]];
     
    //参数结束
    [body appendData:[self getDataWithString:@"--BOUNDARY--\r\n"]];
    request.HTTPBody = body;
    
    //设置请求体长度
    NSInteger length = [body length];
    [request setValue:[NSString stringWithFormat:@"%ld",length] forHTTPHeaderField:@"Content-Length"];
    //设置 POST请求文件上传
    [request setValue:@"multipart/form-data; boundary=BOUNDARY" forHTTPHeaderField:@"Content-Type"];
    
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        NSJSONSerialization *object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSDictionary *dict = (NSDictionary *)object;
        NSLog(@"=====%@",[dict objectForKey:@"success"]);
    }];
    //开始任务
    [dataTask resume];
    
}

-(NSData *)getDataWithString:(NSString *)string{
    
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    
    return data;
}

这里的参数是img_base64:imageData uid:uid
本人也是在踩坑的路上不断前进,希望对大家有用


文章作者: 小小学生
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小小学生 !
评论
  目录