写在前面:

在iOS开发的过程中,有很多时候我们都在和数据打交道,最基本的就是数据的下载和上传了,估计很多很多的小伙伴都在用AFNetworking与后台数据打交道,可有没有想过,哪天AFNetworking你不能用了或者不会用了怎么办?可能你心中疑惑了,这三方只要更新,存在怎么会不能用或者我怎么会不会用了,在没有看Telegram源码之前,我也是这么想的,看了Telegram源码就不会再这么想了,以后我会把自己看的Telegram源码部分的总结和经验一点点的整理分享出来,整理成这个Telegram学习解析系列,有兴趣的同行可以加文章链接最后面的telegram开发学习群,一起学习讨论Telegram问题,Android和iOS都可以。一起进步!

需求怎样来的?

先看看这个,在Telegram的安全协议 MtProtoKit中,你可以看到这个Third Party 这个文件,看下面的截图:

可以看到这里面是有AFNetworking的,这个框架里面的东西有写就是集成字AF来写的,但AF这个版本是挺低的,尝试着自己在这个基础上去写上传那些方法应该是可以,我尝试过之后放弃了,还是决定利用 NSURLConnection / NSURLSessionDataTask来自己写,不过这个的话就的涉及到了请求这些东西的一个封装,以及利用这个上传图片或者语音什么的时候,还有里面的参数的一个组装,接下来就认真的把这部分的东西写出来,这也是在Telegram的基础上衍生出来的问题,要是平常的项目中,可能也不会轻易涉及到这些东西,既然用到了就好好总结一下:

一:简单的数据访问

先从简单的开始,就从你给后台Post数据开始,先从NSURLConnection开始,下面的代码就是具体的实例,每一句都有具体的注释,看代码:

  1. -(NSString * )httpRequestWithParameters:(NSDictionary*)dict andURL:(NSURL*)url{
  2.  
  3. //把参数字典转化成Data
  4. NSData * postData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:NULL];
  5. //把Data利用这个Key加密,这个Key自己设置
  6. NSString * key = @"********";
  7. postData = [postData AES256_Encrypt:key];
  8. //初始化request
  9. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  10. //设置请求方式
  11. [request setHTTPMethod:@"POST"];
  12. //添加请求体,这里要进行64编码处理,就是这个newStringInBase64FromData方法
  13. [request setHTTPBody:[[postData newStringInBase64FromData] dataUsingEncoding:NSUTF8StringEncoding]];
  14. //设置请求的报文
  15. [request setValue:@"utf-8" forHTTPHeaderField:@"charset"];
  16. [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  17. //请求超时时间设置
  18. [request setTimeoutInterval:15.0];
  19.  
  20. NSOperationQueue * queue = [[NSOperationQueue alloc]init];
  21. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * response, NSData *data, NSError *error){
  22.  
  23. if(error){
  24. NSLog(@"文本内容上传失败");
  25. NSLog(@"%@",data);
  26. NSLog(@"%@",response);
  27. }else{
  28. // 解析服务器返回的数据(解析成字符串)
  29. NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  30. NSLog(@"解析服务器返回的数据====%@", string);
  31. }
  32. }];
  33. }

注意:关于配置报文下面这篇文章   POST请求的forHTTPHeaderField   感谢作者。

上面方法那些编码、加密方法,你要有需要的话可以在我首页找到我Q,我发给你。

上面的方法你可以给后台去POST数据,再说剩下的这个 NSURLSessionDataTask ,其实苹果是不建议使用前面的 NSURLConnection 了的,这个我们就说的简单点,你怎么从后台请求数据,下面就但是一个简单的Get方法,请求Request部分的我们就不说了,和上面的一样,参考上面的就行,下面就是一个完整的方法,你通过请求获取到数据回调的方法:

  1. -(void)httpRequestWithURL:(NSURL*)url andHttpRequestSuccess:(HttpRequestSuccess)httpRequestSuccess andHttpRequestFail:(HttpRequestFail)httpRequestFail{
  2.  
  3. //推荐使用这种请求方法,上面的方已经被废弃
  4. //下面的方法没有给Request设置请求头和内容,有需要参考上面的写法
  5. NSURLSession * session = [NSURLSession sharedSession];
  6. NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:[NSURLRequest requestWithURL:url] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  7.  
  8. if (!error) {
  9. //没有错误,返回正确
  10. NSError * jsonError;
  11. NSDictionary * dic =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
  12. if (!jsonError) {
  13. httpRequestSuccess(dic);
  14. }
  15. }else{
  16. //请求出现错误
  17. httpRequestFail(@"请求错误");
  18. }
  19. NSLog(@"response==%@",response);
  20. }];
  21. [dataTask resume];
  22. }

上面的这些就把简单的怎样和后台进行数据交互就解决了,当然这试试简单的,涉及到文件下载上传的我们就下面接着说:

二 :涉及到文件类型的怎么处理

下面这个方法是在处理Telegram消息类型上传数据给后台的时候添加的,这个方法可能里面纳西而判断等等的东西你用不着,主要的你看里面上传部分的内容封装吧,主要的还是这部分的东西,或者对这个方法里面还有什么疑问的,可以问我。方法我直接给出来,里面的注释真的挺详细的了。一句一句的过:

  1. /**
  2. 上传Data
  3.  
  4. @param url 上传DataUrl
  5. @param postParems 参数
  6. @param picFilePath 文件路径
  7. @param picFileName 文件名称,
  8. @param message_Type 消息类型(区分你要上传的文件是什么类型的,图片、视频、语音等等)
  9. @param fileName 这是像PDF,TXT等格式问文件的文件名
  10. @return return value description
  11. */
  12. + (NSString *)postRequestWithURL: (NSString *)url postParems: (NSMutableDictionary *)postParems picFilePath: (NSString *)picFilePath picFileName: (NSString *)picFileName andMessageType:(Message_Type)message_Type andFileName:(NSString *)fileName{
  13.  
  14. /**
  15. boundary: 是分隔符号,告诉服务器,我的请求体里用的就是就是这个分隔符,而且,拼接请求体也用到这个分隔符
  16. */
  17. NSString *TWITTERFON_FORM_BOUNDARY = @"iOSFileUploaded";
  18. //根据url初始化request
  19. NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
  20. cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
  21. timeoutInterval:10];
  22. //分界线 --AaB03x
  23. NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
  24. //结束符 AaB03x--
  25. NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
  26.  
  27. NSData * data;
  28. NSString * format; // 文件上传的格式
  29. //得到图片的data
  30. if (message_Type == ImageMessage) {
  31.  
  32. format = @" image/jpge,image/gif, image/jpeg, image/pjpeg, image/pjpeg";
  33. UIImage *image=[UIImage imageWithContentsOfFile:picFilePath];
  34. //返回为JPEG图像
  35. data = UIImageJPEGRepresentation(image, 0.3f);
  36.  
  37. //得到语音或者视频的data
  38. }else if (message_Type == VoiceMessage){
  39.  
  40. format = @"audio/mp3";
  41. data= [NSData dataWithContentsOfFile:picFilePath];
  42. }else if (message_Type == VedioMessage){
  43.  
  44. format = @"audio/mp4";
  45. [self convertVideoWithModel:picFilePath andUrl:url andNSDictionary:postParems];
  46. return @"进入了视频压缩";
  47. }else if (message_Type == PasterMessage){
  48.  
  49. format = @"image/webp";//webp图片格式
  50. data = [NSData dataWithContentsOfFile:picFilePath];
  51. }else if (message_Type == FileMessage){
  52.  
  53. format = [self GetContentType:fileName]; //判断文件的上传格式,利用后缀名判断
  54. data = [NSData dataWithContentsOfFile:picFilePath];
  55. }
  56. // 在这里判断Data是否存在
  57. if (!data) {
  58.  
  59. NSLog(@"要上传的data不存在");
  60. return @"data不存在";
  61. }
  62. //http body的字符串
  63. NSMutableString *body=[[NSMutableString alloc]init];
  64. //参数的集合的所有key的集合
  65. NSArray *keys= [postParems allKeys];
  66. //遍历keys
  67. for(int i=0;i<(int)[keys count];i++){
  68. //得到当前key
  69. NSString *key=[keys objectAtIndex:i];
  70. //添加分界线,换行
  71. [body appendFormat:@"%@\r\n",MPboundary];
  72. //添加字段名称,换2行
  73. [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
  74. //添加字段的值
  75. [body appendFormat:@"%@\r\n",[postParems objectForKey:key]];
  76. }
  77. if(picFileName){
  78.  
  79. ////添加分界线,换行
  80. [body appendFormat:@"%@\r\n",MPboundary];
  81.  
  82. //声明pic字段,文件名为boris.png
  83. [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",FORM_FLE_INPUT,picFileName];
  84. //声明上传文件的格式
  85. NSString * formant = [NSString stringWithFormat:@"Content-Type:%@\r\n\r\n",format];
  86. [body appendFormat:@"%@", formant];
  87. }
  88.  
  89. //声明结束符:--AaB03x--
  90. NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
  91. //声明myRequestData,用来放入http body
  92. NSMutableData *myRequestData=[NSMutableData data];
  93.  
  94. //将body字符串转化为UTF8格式的二进制
  95. [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
  96. if(data){
  97.  
  98. [myRequestData appendData:data];
  99. }
  100. //加入结束符--AaB03x--
  101. [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
  102.  
  103. //设置HTTPHeader中Content-Type的值
  104. NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
  105. //设置HTTPHeader
  106. [request setValue:content forHTTPHeaderField:@"Content-Type"];
  107. //设置Content-Length
  108. [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[myRequestData length]] forHTTPHeaderField:@"Content-Length"];
  109. //设置http body
  110. [request setHTTPBody:myRequestData];
  111. //http method
  112. [request setHTTPMethod:@"POST"];
  113.  
  114. NSHTTPURLResponse *urlResponese = nil;
  115. NSError * error = [[NSError alloc]init];
  116. NSData * resultData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponese error:&error];
  117.  
  118. NSDictionary * JSONresponseObject = [NSJSONSerialization JSONObjectWithData:resultData options:NSJSONReadingMutableContainers error:nil];
  119. if ([[NSString stringWithFormat:@"%@",JSONresponseObject[@"errorCode"]] isEqualToString:@"0"]) {
  120.  
  121. NSString *string = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
  122. NSLog(@"解析服务器返回的字符串====%@", string);
  123. NSLog(@"解析服务器返回的字典 ====%@", JSONresponseObject);
  124. return @"200";
  125. }
  126. return nil;
  127. }

为了不让博客篇幅太长,上面涉及到的视频压缩,还有文件的后缀名的判断方法就不在发出来了,到时这个消息类型的判断,这个我觉得是有必要发出来的,不是说这个有多复杂,只是可能找起来没那么容易能找打一份完整的,既然能看到这,估计可能有伙伴会有需要的:

  1. /*** 根据文件类型判断上传的文件格式 ***/
  2. +(NSString*)GetContentType:(NSString*)filename{
  3.  
  4. // 判断之前先把文件名称转化成小写
  5. NSString * Filename = [filename lowercaseString];
  6.  
  7. if ([Filename hasSuffix:@"avi"]) {
  8.  
  9. return @"video/avi";
  10. }
  11. else if([Filename hasSuffix:@"bmp"])
  12. {
  13. return @"application/x-bmp";
  14. }
  15. else if([Filename hasSuffix:@"jpeg"])
  16. {
  17. return @"image/jpeg";
  18. }
  19. else if([Filename hasSuffix:@"jpg"])
  20. {
  21. return @"image/jpeg";
  22. }
  23. else if([Filename hasSuffix:@"png"])
  24. {
  25. return @"image/x-png";
  26. }
  27. else if([Filename hasSuffix:@"mp3"])
  28. {
  29. return @"audio/mp3";
  30. }
  31. else if([Filename hasSuffix:@"mp4"])
  32. {
  33. return @"video/mpeg4";
  34. }
  35. else if([Filename hasSuffix:@"rmvb"])
  36. {
  37. return @"application/vnd.rn-realmedia-vbr";
  38. }
  39. else if([Filename hasSuffix:@"txt"])
  40. {
  41. return @"text/plain";
  42. }
  43. else if([Filename hasSuffix:@"xsl"])
  44. {
  45. return @"application/x-xls";
  46. }
  47. else if([Filename hasSuffix:@"xslx"])
  48. {
  49. return @"application/x-xls";
  50. }
  51. else if([Filename hasSuffix:@"xwd"])
  52. {
  53. return @"application/x-xwd";
  54. }
  55. else if([Filename hasSuffix:@"doc"])
  56. {
  57. return @"application/msword";
  58. }
  59. else if([Filename hasSuffix:@"docx"])
  60. {
  61. return @"application/msword";
  62. }
  63. else if([Filename hasSuffix:@"ppt"])
  64. {
  65. return @"application/x-ppt";
  66. }
  67. else if([Filename hasSuffix:@"pdf"])
  68. {
  69. return @"application/pdf";
  70. }
  71. return nil;
  72. }

Telegram学习解析系列(二):这我怎么给后台传输数据?的更多相关文章

  1. Telegram学习解析系列(一):认识一下Telegram的源码

    前言: Telegram不知道有多少同行听过这玩意,或者在看它的源码.我是出于工作原因才接触到这东西,看的真是的......变方了!一个月估计刚刚找到门,还没进去多深,把自己的心得和对源码的认识以及我 ...

  2. Telegram学习解析系列(三) : Build Telegram报错分析总结

    正好通过这次 Telegram 的运行,很想把常见的项目运行的错误好好的总结一下,在前面的博客中,又星星散散的总结过错误和一些警告的消除方法,这次把错误处理一下,还有Telegram项目中有999+的 ...

  3. java基础解析系列(二)---Integer

    java基础解析系列(二)---Integer 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现bug的时候,才能处理更加从容. 目录 java基础解析 ...

  4. ETL利器Kettle实战应用解析系列二

    本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle ...

  5. Socket学习总结系列(二) -- CocoaAsyncSocket

    这是系列的第二篇 这是这个系列文章的第二篇,要是没有看第一篇的还是建议看看第一篇,以为这个是接着第一篇梳理的 先大概的总结一下在上篇的文章中说的些内容: 1. 整理了一下做IM我们有那些途径,以及我们 ...

  6. ETL利器Kettle实战应用解析系列二 【应用场景和实战DEMO下载】

    本文主要阅读目录如下: 1.应用场景 2.DEMO实战 3.DEMO下载 1.应用场景 这里简单概括一下几种具体的应用场景,按网络环境划分主要包括: 表视图模式:这种情况我们经常遇到,就是在同一网络环 ...

  7. 小白学习Spark系列二:spark应用打包傻瓜式教程(IntelliJ+maven 和 pycharm+jar)

    在做spark项目时,我们常常面临如何在本地将其打包,上传至装有spark服务器上运行的问题.下面是我在项目中尝试的两种方案,也踩了不少坑,两者相比,方案一比较简单,本博客提供的jar包适用于spar ...

  8. 学习CNN系列二:训练过程

    卷积神经网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间精确的数学表达式,只要用已知的模式对卷积神经网络加以训练,网络就具有输入.输出之间映射的 ...

  9. Dubbo源码学习总结系列二 dubbo-rpc远程调用模块

    dubbo本质是一个RPC框架,我们首先讨论这个骨干中的骨干,dubbo-rpc模块. 主要讨论一下几部分内容: 一.此模块在dubbo整体框架中的作用: 二.此模块需要完成的需求功能点及接口定义: ...

随机推荐

  1. linux ip 转发设置 ip_forward

    工作原理: 内网主机向公网发送数据包时,由于目的主机跟源主机不在同一网段,所以数据包暂时发往内网默认网关处理,而本网段的主机对此数据包不做任何回应.由于源主机ip是私有的,禁止在公网使用,所以必须将数 ...

  2. MySQL从库忽略某些错误

    z熬配置MySQL主从同步的时候常常会因为主库的中SQL语句的错误造成从库的同步出现错误,一旦从库同步出现错误就会造成同步的卡壳影响后续的同步: 可以在从库的配置文件中加入如下的参数,使从库可以自动忽 ...

  3. 免费SSL证书PK付费SSL证书 花落谁家

    3月17日和18日,Google Chrome 57.0.2987.110与Mozilla Firefox 52.0.1分别上线,而这两款浏览器都出现了一个共同点:打压HTTP协议.在Firefox ...

  4. JAVA-实例方法被覆盖,静态方法被隐藏Explain

    被覆盖比较好理解,类似于多态的实现. 被隐藏是指静态方法的访问是根据当前对象的表面类型来决定的,比如 Supers = new Sub(); s.greeting()访问的是Super的静态方法,如果 ...

  5. 【2017-04-01】JS字符串的操作、时间日期的操作、函数、事件、动画基础

    一.字符串的操作 1.转大写: s.toLowerCase(); 2.转大写: s.toUpperCase(); 3.字符串的截取: s.substr(3,4);      -从索引3开始截取,截取4 ...

  6. 手机自动化测试:appium源码分析之bootstrap十七

    手机自动化测试:appium源码分析之bootstrap十七   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...

  7. jquery的冒泡事件event.stopPropagation()

    js中的冒泡事件与事件监听 冒泡事件 js中“冒泡事件”并不是能实际使用的花哨技巧,它是一种对js事件执行顺序的机制,“冒泡算法”在编程里是一个经典问题,冒泡算法里面的冒泡应该 说是交换更加准确:js ...

  8. ecshop3.6商品如何按照销量排序

    ecshop订单状态对应值:order_status有5中状态,并且当客户确认收货后,order_status的数值不一定是1也有可能是5.order_status = 0表示订单未确认order_s ...

  9. (转)混乱的First、Follow、Firstvt和Lastvt

    转自: http://dongtq2010.blog.163.com/blog/static/1750224812011520113332714/ 学编译原理的时候,印象最深的莫过于这四个集合了,而且 ...

  10. Mac OS平台下应用程序安装包制作工具Packages的使用介绍(补充)

    上一篇:Mac OS平台下应用程序安装包制作工具Packages的使用介绍 补充说明 上一篇文章中介绍了如何使用Packages如何创建mac下的安装包.但是这样制作出来的安装包只能安装到系统的文件路 ...