Telegram学习解析系列(二):这我怎么给后台传输数据?

写在前面:

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

需求怎样来的?

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

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

一:简单的数据访问

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

 -(NSString * )httpRequestWithParameters:(NSDictionary*)dict andURL:(NSURL*)url{

         //把参数字典转化成Data
         NSData * postData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:NULL];
         //把Data利用这个Key加密,这个Key自己设置
         NSString * key = @"********";
         postData = [postData AES256_Encrypt:key];
         //初始化request
         NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
         //设置请求方式
         [request setHTTPMethod:@"POST"];
         //添加请求体,这里要进行64编码处理,就是这个newStringInBase64FromData方法
         [request setHTTPBody:[[postData newStringInBase64FromData] dataUsingEncoding:NSUTF8StringEncoding]];
         //设置请求的报文
         [request setValue:@"utf-8" forHTTPHeaderField:@"charset"];
         [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
         //请求超时时间设置
         [request setTimeoutInterval:15.0];

         NSOperationQueue * queue = [[NSOperationQueue alloc]init];
         [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * response, NSData *data, NSError *error){

                 if(error){
                     NSLog(@"文本内容上传失败");
                     NSLog(@"%@",data);
                     NSLog(@"%@",response);
                 }else{
                    // 解析服务器返回的数据(解析成字符串)
                    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                    NSLog(@"解析服务器返回的数据====%@", string);
                 }
         }];
 }

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

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

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

-(void)httpRequestWithURL:(NSURL*)url andHttpRequestSuccess:(HttpRequestSuccess)httpRequestSuccess  andHttpRequestFail:(HttpRequestFail)httpRequestFail{

     //推荐使用这种请求方法,上面的方已经被废弃
     //下面的方法没有给Request设置请求头和内容,有需要参考上面的写法
     NSURLSession * session = [NSURLSession sharedSession];
     NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:[NSURLRequest requestWithURL:url] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

       if (!error) {
         //没有错误,返回正确
         NSError * jsonError;
         NSDictionary * dic =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
         if (!jsonError) {
             httpRequestSuccess(dic);
         }
       }else{
         //请求出现错误
         httpRequestFail(@"请求错误");
       }
       NSLog(@"response==%@",response);
    }];
    [dataTask resume];
}

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

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

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

/**
 上传Data

 @param url           上传DataUrl
 @param postParems    参数
 @param picFilePath   文件路径
 @param picFileName   文件名称,
 @param message_Type  消息类型(区分你要上传的文件是什么类型的,图片、视频、语音等等)
 @param fileName      这是像PDF,TXT等格式问文件的文件名
 @return return value description
 */
+ (NSString *)postRequestWithURL: (NSString *)url postParems: (NSMutableDictionary *)postParems picFilePath: (NSString *)picFilePath picFileName: (NSString *)picFileName  andMessageType:(Message_Type)message_Type andFileName:(NSString *)fileName{

    /**
     boundary: 是分隔符号,告诉服务器,我的请求体里用的就是就是这个分隔符,而且,拼接请求体也用到这个分隔符
     */
    NSString *TWITTERFON_FORM_BOUNDARY = @"iOSFileUploaded";
    //根据url初始化request
    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                           cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                       timeoutInterval:10];
    //分界线 --AaB03x
    NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
    //结束符 AaB03x--
    NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];

    NSData * data;
    NSString * format; // 文件上传的格式
    //得到图片的data
    if (message_Type == ImageMessage) {

        format = @" image/jpge,image/gif, image/jpeg, image/pjpeg, image/pjpeg";
        UIImage *image=[UIImage imageWithContentsOfFile:picFilePath];
        //返回为JPEG图像
        data = UIImageJPEGRepresentation(image, 0.3f);

    //得到语音或者视频的data
    }else if (message_Type == VoiceMessage){

        format = @"audio/mp3";
        data= [NSData dataWithContentsOfFile:picFilePath];
    }else if (message_Type == VedioMessage){

        format = @"audio/mp4";
        [self convertVideoWithModel:picFilePath andUrl:url andNSDictionary:postParems];
        return @"进入了视频压缩";
    }else if (message_Type == PasterMessage){

        format = @"image/webp";//webp图片格式
        data = [NSData dataWithContentsOfFile:picFilePath];
    }else if (message_Type == FileMessage){

         format = [self GetContentType:fileName]; //判断文件的上传格式,利用后缀名判断
         data   = [NSData dataWithContentsOfFile:picFilePath];
    }
    // 在这里判断Data是否存在
    if (!data) {

        NSLog(@"要上传的data不存在");
        return @"data不存在";
    }
    //http body的字符串
    NSMutableString *body=[[NSMutableString alloc]init];
    //参数的集合的所有key的集合
    NSArray *keys= [postParems allKeys];
    //遍历keys
    for(int i=0;i<(int)[keys count];i++){
        //得到当前key
        NSString *key=[keys objectAtIndex:i];
        //添加分界线,换行
        [body appendFormat:@"%@\r\n",MPboundary];
        //添加字段名称,换2行
        [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
        //添加字段的值
        [body appendFormat:@"%@\r\n",[postParems objectForKey:key]];
    }
    if(picFileName){

        ////添加分界线,换行
        [body appendFormat:@"%@\r\n",MPboundary];

        //声明pic字段,文件名为boris.png
        [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",FORM_FLE_INPUT,picFileName];
        //声明上传文件的格式
        NSString * formant = [NSString stringWithFormat:@"Content-Type:%@\r\n\r\n",format];
        [body appendFormat:@"%@", formant];
    }

    //声明结束符:--AaB03x--
    NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
    //声明myRequestData,用来放入http body
    NSMutableData *myRequestData=[NSMutableData data];

    //将body字符串转化为UTF8格式的二进制
    [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
    if(data){

        [myRequestData appendData:data];
    }
    //加入结束符--AaB03x--
    [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];

    //设置HTTPHeader中Content-Type的值
    NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
    //设置HTTPHeader
    [request setValue:content forHTTPHeaderField:@"Content-Type"];
    //设置Content-Length
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[myRequestData length]] forHTTPHeaderField:@"Content-Length"];
    //设置http body
    [request setHTTPBody:myRequestData];
    //http method
    [request setHTTPMethod:@"POST"];

    NSHTTPURLResponse *urlResponese = nil;
    NSError * error = [[NSError alloc]init];
    NSData  * resultData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponese error:&error];

    NSDictionary * JSONresponseObject = [NSJSONSerialization JSONObjectWithData:resultData options:NSJSONReadingMutableContainers error:nil];
    if ([[NSString stringWithFormat:@"%@",JSONresponseObject[@"errorCode"]] isEqualToString:@"0"]) {

        NSString *string = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
        NSLog(@"解析服务器返回的字符串====%@", string);
        NSLog(@"解析服务器返回的字典  ====%@", JSONresponseObject);
        return @"200";
    }
    return nil;
}

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

/*** 根据文件类型判断上传的文件格式 ***/
+(NSString*)GetContentType:(NSString*)filename{

    // 判断之前先把文件名称转化成小写
    NSString * Filename = [filename lowercaseString];

    if ([Filename hasSuffix:@"avi"]) {

        return @"video/avi";
    }
    else if([Filename hasSuffix:@"bmp"])
    {
        return @"application/x-bmp";
    }
    else if([Filename hasSuffix:@"jpeg"])
    {
        return @"image/jpeg";
    }
    else if([Filename hasSuffix:@"jpg"])
    {
        return @"image/jpeg";
    }
    else if([Filename hasSuffix:@"png"])
    {
        return @"image/x-png";
    }
    else if([Filename hasSuffix:@"mp3"])
    {
        return @"audio/mp3";
    }
    else if([Filename hasSuffix:@"mp4"])
    {
        return @"video/mpeg4";
    }
    else if([Filename hasSuffix:@"rmvb"])
    {
        return @"application/vnd.rn-realmedia-vbr";
    }
    else if([Filename hasSuffix:@"txt"])
    {
        return @"text/plain";
    }
    else if([Filename hasSuffix:@"xsl"])
    {
        return @"application/x-xls";
    }
    else if([Filename hasSuffix:@"xslx"])
    {
        return @"application/x-xls";
    }
    else if([Filename hasSuffix:@"xwd"])
    {
        return @"application/x-xwd";
    }
    else if([Filename hasSuffix:@"doc"])
    {
        return @"application/msword";
    }
    else if([Filename hasSuffix:@"docx"])
    {
        return @"application/msword";
    }
    else if([Filename hasSuffix:@"ppt"])
    {
        return @"application/x-ppt";
    }
    else if([Filename hasSuffix:@"pdf"])
    {
        return @"application/pdf";
    }
    return nil;
}

好了,上面就是完整的能够上传文件、语音或者视频的方法,要是有什么疑问可以随时来找我,还有就是下面的这个Telegram学习群,有相同兴趣爱好的朋友可以加进来,大家一起学习进步。

*****************  群号可以直接粘贴这里:485718322

时间: 2024-10-09 21:18:29

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

学习CNN系列二:训练过程

卷积神经网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间精确的数学表达式,只要用已知的模式对卷积神经网络加以训练,网络就具有输入.输出之间映射的能力. 其训练算法与传统的BP算法类似,主要分4步,可分为2个阶段: 第一阶段,前向传播阶段: (1)从样本集中取一个样本,将样本输入网络: (2)计算相应的实际输出. 在此阶段,信息从输入层经过逐级的变换,传送到输出层.这个过程也是网络在完成训练后正常运行时执行的过程. 第二阶段,后向传播阶段:

重新学习python系列(二)? WTF?

判断class的类型,可以使用isinstance()函数. isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上. >>> a = Animal() >>> d = Dog() >>> h = Husky()>>> isinstance(h, Husky) True>>> isinstance(h, Dog) True 能用type()判断的基本类型也可以用isinstance()判

Windows-universal-samples学习笔记系列二:Controls, layout, and text

Controls, layout, and text AutoSuggestBox migration Clipboard Commanding Context menu Context menu (XAML) Disabling selection Display orientation Downloadable fonts (DirectWrite) Downloadable fonts (XAML) Drag and drop Focus visuals Full screen mode

Tomcat总体架构(Tomcat源码解析系列二)

Tomcat即是一个HTTP服务器,也是一个servlet容器,主要目的就是包装servlet,并对请求响应相应的servlet,纯servlet的web应用似乎很好理解Tomcat是如何装载servlet的,但,当使用一些MVC框架时,如spring MVC.strusts2,可能就找不出servlet在哪里?其实spring MVC框架就是一整个servlet,在web.xml中配置如下: <!-- Spring MVC servlet --> <servlet> <se

(转)ETL利器Kettle实战应用解析系列一【Kettle使用介绍】

原文地址:http://www.cnblogs.com/limengqiang/archive/2013/01/16/KettleApply1.html 本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle实战应用解析系列三 [ETL后台进程执行配置方式] 本文主要阅读目录如下: 1.Kettle概念 2.下载和部署 3.Kettle环境配置 4.K

ETL利器Kettle实战应用解析系列一【Kettle使用介绍】

本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle实战应用解析系列三 [ETL后台进程执行配置方式] 本文主要阅读目录如下: 1.Kettle概念 2.下载和部署 3.Kettle环境配置 4.Kettle使用及组件介绍 ETL(Extract-Transform-Load的缩写,即数据抽取.转换.装载的过程),对于企业或行业应用来说,我们经常会遇

java基础解析系列(十一)---equals、==和hashcode方法

java基础解析系列(十一)---equals.==和hashcode方法 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及装箱拆箱 java基础解析系列(三)---HashMap原理 java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现 java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别 j

ASP.NET MVC学习系列(二)-WebAPI请求

继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现数据调用. 继续使用上一文章中的示例,添加一个index.html页面,添加对jquery的引用. 一.无参数Get请求 一般的get请求我们可以使用jquery提供的$.get() 或者$.ajax({type:"get"}) 来实现: 请求的后台Action方法仍为上篇文章中的GetU

oracle学习入门系列之二 数据库基础知识

oracle学习入门系列之二 数据库基础知识 本篇蛤蟆要梳理下那些被淡忘的数据库基础知识,也许根本就没被人记住过.不管是哪种情况,该记住的必须记住,记不住就把他记下来吧. 首先问几个问题如下: 数据库基础知识是什么? 好吧,蛤蟆直接吐后而不亡,看目录开始吧. 本人邮箱:[email protected] 微信公众号:HopToad 欢迎各界交流 1      基本概念 概念就是概念,大伙对这些名词不要死磕,但是对定义一定要理解,理解方能领悟,领悟方能运用自如后创新. 1.1      数据 数据