IOS开发笔记(十一)——上传用户头像,multipart/form-data图片上传

中山大学数据科学与计算机学院本科生实验报告

(2019年春季学期)


一、实验题目

IM聊天工具

二、实现内容

  • 用户登陆后拉取用户信息
  • 上传用户头像,multipart/form-data图片上传
  • 修改用户个人详情,与服务器交互

三、实验结果

1. 用户登陆后拉取用户信息

用户登陆成功后,后台仅会返回成功的提示,需要客户端再次进行网络请求来获取这个用户的信息。之前我们的做法是固定的定义UserModel,这样子无法获取更新后的信息,只是能得到这个用户注册时的信息,再他修改个人详情后无法动态更新。这周由我来通过网络请求来动态获取用户的信息。

// 获取用户的信息
-(void) getInfo{
    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    // 定义url
    NSString *url = @"http://172.18.32.97:8000/account/info";
    // 定义成功回调函数
    [manger GET:url parameters:nil progress:nil
        success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"getInfo success");
            self.loginUser = [[UserModel alloc] 
                             initWithProperties:responseObject[@"data"][@"Username"] 
                              NickName:responseObject[@"data"][@"Nickname"]
                              RemarkName:responseObject[@"data"][@"Username"]
 							  Gender:responseObject[@"data"][@"Gender"]
                              Birthplace:responseObject[@"data"][@"Region"]
                              ProfilePicture:@"peppa"];
    }
        failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"getInfo fail");
            NSLog(error.localizedDescription);
    }];
}

当成功获取后,将UserModel初始化为从服务器获取的信息。

该函数在用户成功登陆后使用。

if([result[@"state"] isEqualToString:@"ok"])
{
    NSLog(@"login success");
    
    // 登陆成功后,获取用户的个人信息
    [self getInfo];
    
    // ···
}
else
{
    NSLog(@"login fail");
}
2. 读取图像后显示,上传用户头像,multipart/form-data图片上传

在上周,我已经完成了图片从图库的读取,但仍未能更新在tableview中。这周经过仔细的查看,发现是因为我tableview的数据源没有更新为图库读取出来的信息,所以不能更新成功。这里我新定义一个ImageView来存储图库中读取的图片,当回调函数调用的时候,就通知tableview要使用我这个imageView来进行显示。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *) info{
    // 定义一个newPhoto,用来存放我们选择的图片。
    UIImage *newPhoto = [info objectForKey:@"UIImagePickerControllerEditedImage"];
	// NSLog(urlStr);
    [self dismissViewControllerAnimated:YES completion:nil];
    self.User.ProfilePicture = @"image";
    UIImageView *imageView = [[UIImageView alloc] initWithImage:newPhoto];
    self.head = imageView;
    [self.tableView reloadData];
    
    // 上传到云端
    [[UserManager getInstance] uploadImage:@"/account/info/avatar" withImage:newPhoto];   
}

完成显示后,下一步要进行的就是上传服务器的工作。这里服务器提供的接口是需要上传form-data/multipart的文件,这与其他个人信息改变有些区别,不是简单的键值对。这里我使用到了AFNetworking的第三方网络开源工具库。

这里有几个关键的步骤:

  • 定义session 设置为multipart/form-data
  • 处理url,定义好api
  • 将UIImage图片转成NSData
  • 将NSData加入到formData后就可以执行post请求
  • 处理上传结果回调
// 上传图片到服务器
-(void) uploadImage:(NSString* )path withImage:(UIImage* )image
{
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    [session.requestSerializer setValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"];
    
    // 处理url
    NSString* serverDomain = @"http://172.18.32.97:8000";
    NSString* urlString = [serverDomain stringByAppendingString:path];
    NSLog(urlString);
    [session POST:urlString parameters:nil constructingBodyWithBlock:
     ^(id<AFMultipartFormData> _Nonnull formData){
        // 图片转data
        NSData *data = UIImagePNGRepresentation(image);
        [formData appendPartWithFileData :data name:@"file" fileName:@"iName.png"
                                 mimeType:@"multipart/form-data"];
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject){
        NSLog(@"uploadImage success");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error){
        NSLog(@"uploadImage fail");
        NSLog(error.localizedDescription);
    }];
}

实现效果图:

修改前
在这里插入图片描述

修改后

4

3. 修改用户个人详情,与服务器交互

修改用户个人详情,包括修改用户的昵称,性别,地区的信息。这些都是可以通过键值对来进行修改,比修改图片要容易,这里利用tableview的选择函数进行判断,修改的是哪一个内容,然后再根据这个内容选择不同的api进行修改。

// 上传到云端
if ([str isEqualToString:@"昵称"])
    [[UserManager getInstance] modifyInfo:@"Nickname" withValue:self.User.NickName];
else if ([str isEqualToString:@"性别"])
    [[UserManager getInstance] modifyInfo:@"Gender" withValue:self.User.Gender];
else if ([str isEqualToString:@"地区"])
    [[UserManager getInstance] modifyInfo:@"Region" withValue:self.User.Birthplace];

modifyInfo函数

  • 定义参数
  • 定义handler
  • 定义api
  • 使用之前实现的SessionHelper工具类进行put请求,修改用户对应属性的值
// 根据要修改的属性attr,与修改后的值value来调用网络api
-(void) modifyInfo:(NSString *)attr withValue:(NSString *)value
{
    void (^modifyInfoEvent)(id) = ^void (id object)
    {
        NSDictionary *result = object;
        if([result[@"state"] isEqualToString:@"ok"])
        {
            NSLog(@"modifyInfo success");
        }
        else
        {
            NSLog(result[@"msg"]);
            NSLog(@"modifyInfo fail");
        }
    };
    NSString *params = [[NSString alloc] initWithFormat:@"value=%@", value];
    NSString *api = [[NSString alloc] initWithFormat:@"/account/info/%@", attr];
    NSLog(api);
    NSLog(params);
    [SessionHelper sendRequest:api method:@"put" parameters:params handler:modifyInfoEvent];
}

SessionHelper

#import "SessionHelper.h"

NSString* const SERVER_DOMAIN = @"http://118.89.65.154:8000";

@implementation SessionHelper

+ (void)sendRequest:(NSString*)path method:(NSString*)method parameters:(NSString*)parameters handler:(void(^)(id))handler
{
    //NSString* serverDomain = @"http://172.18.32.97:8000";
    //NSString* serverDomain = @"http://118.89.65.154:8000";
    NSString* urlString = [SERVER_DOMAIN stringByAppendingString:path];
    NSURL *url = [NSURL URLWithString:urlString];
    
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
    
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    
    [urlRequest setHTTPMethod:method];
    if (![parameters isEqual: @""])
    {
        NSString *params = [[NSString alloc] initWithString:parameters];
        [urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
    }
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
    {
        if(error == nil)
        {
            if(NSClassFromString(@"NSJSONSerialization"))
            {
                NSError *parseError = nil;
                id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
                if(parseError)
                {
                    NSLog(@"parse error: %@", parseError);
                }
                if([object isKindOfClass:[NSDictionary class]])
                {
                    handler(object);
                }
                else
                {
                    NSLog(@"Not dictionary");
                }
            }
        }
        else
        {
            NSLog(@"Network error:%@", error);
        }
    }];
    
    [task resume];
}

@end

实现效果图:

修改前

1

修改后

2

四、实验思考及感想

​ 本周的展示,我们小组也基本把当前的情况说明了一下,进度不错,其中的问题也咨询了字节的工程师,在进行改进或者做一些额外需求加分项。这周我主要的工作是进行网络访问,连接后台修改个人信息等,其中最为难的部分是对于图片的处理,因为之前都是在修改文字比较直观,而到了图片需要转换的格式也不一样。在我与后台的同学互相研究后,终于也实现了上传修改图片等功能。我实现了个上传图片的工具函数,后面做消息传递的时候,发送图片也可以用到,图片问题算是解决了。关于加分项,我们甚至想到了发送视频或者发送语音,这些与后台的交互相信也不简单,留待下一周再进行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值