zoukankan      html  css  js  c++  java
  • iOS图片瘦身总结

    前言

    最近在公司写了个小程序来为iOS应用中的图片瘦身,进而减小APP大小,减少用户下载时的流量。

    瘦身是在一个专门为图片瘦身的网站进行的。

    地址:https://tinypng.com

    这个网站提供的接口是基于https协议的,之前没有怎么用过https协议,现在一并总结一下。

    关于HTTPS

    https协议基础请参考参考:

    HTTPS的七个误解

    其实HTTPS就是安全版本的http协议,

    他采用了RSA非对称加密公私钥对,使用SSL证书验证保证了用户数据在传输时的安全行。

    下面简单看一下http和https请求过程的异同

    我们按个看下流程

    1.客户端向服务端发送基于https的请求。

    2.服务端创建公私钥对。

    3.服务端把共钥绑定在证书上面返回给客户端。

    4.客户端验证证书是否可靠(验证方式有两种,分别针对CA机构办法的证书和自己创建的证书:1.是向颁发证书的CA机构发送请求来验证。2.是在客户端保存一个证书副本,来对比两个证书,同时还会验证是否被中间人进行了攻击,验证方式就是用证书的pubkey去解证书的上密文,如果和证书上的明文一直就可以确定没有被攻击)。

    5.客户端生成一个随机数并用公钥加密传递给服务器。

    6.服务器用私钥解密得到随机数,根据随机数产生对称加密秘钥并用私钥对秘钥进行加密。

    7.传递对称秘钥给客户端。

    8.客户端用公钥解密得到对称加密秘钥。

    以后的通信就会使用对称加密的秘钥来进行了,所以https其实也就第一次请求会比较慢,因为要生成通信对称秘钥,以后再进行通信就和http不会差很多了。

    iOS对于HTTPS的支持

    在说这点之前,先说说tinypng这个网站的接口。

    注册新用户后会返回给你一串key,我们要针对这串key做https请求

    该站采用的是HTTP Basic Auth认证方式(关于Basic Auth认证方式详情参看维基百科)。

    所以我们做请求的时候就需要使用添加headerfield。

    返回的时候会把我们上传图片处理后的下载路径传回来,比较奇葩的是,路径并不在响应体而是在响应头中的Location字段内...(难道图片就不需要保密了么...)。

    下面说说iOS该怎么做,

    iOS的NSURLConnection和NSURLSession的API都提供了很方便的API来支持https请求。

    我在实际操作的时候使用的是NSURLConnection。

    首先创建请求:

     1 NSURL *url = [NSURL URLWithString:REQUEST_URL];
     2 
     3 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
     4 
     5 NSString *basicAuthUsername = BASIC_AUTH_USERNAME;
     6 NSString *basicAuthPassword = BASIC_AUTH_PASSWORD;
     7 NSData *authorizationData = [[NSString stringWithFormat:@"%@:%@",basicAuthUsername,basicAuthPassword] dataUsingEncoding:NSASCIIStringEncoding];
     8 NSString *authorizationStr = [NSString stringWithFormat:@"Basic %@",[authorizationData base64EncodedStringWithOptions:0]];
     9 NSLog(@"%@",authorizationStr);
    10 [request setHTTPMethod:@"POST"];
    11 [request addValue:authorizationStr forHTTPHeaderField:@"Authorization"];
    12 [request addValue:@"*/*" forHTTPHeaderField:@"Accept"];

    URL在API中提供的有,只是协议我们写为HTTPS,然后进行Authorization头字段的拼接,实际上就是Basic base64(用户名:密码)。

    Accept这里设置为了*/*,其实如果知道服务器返回类型可以直接指定application/json或者text/json之类的就行。

    下面看看连接:

    1 -(BOOL)connection:(NSURLConnection*)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace*)protectionSpace
    2 {
    3     return[protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
    4 }
    5 
    6 -(void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge
    7 {
    8     [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    9 }

    我们需要实现NSURLConnectionDelegate,然后实现上面的两个方法。

    第一个方法是判断需要响应哪一类的安全问题,

      NSString *NSURLAuthenticationMethodDefault;

      NSString*NSURLAuthenticationMethodHTTPBasic;

      NSString*NSURLAuthenticationMethodHTTPDigest;

      NSString*NSURLAuthenticationMethodHTMLForm;

      NSString*NSURLAuthenticationMethodNegotiate;

      NSString*NSURLAuthenticationMethodNTLM;

      NSString*NSURLAuthenticationMethodClientCertificate;

      NSString*NSURLAuthenticationMethodServerTrust;

    可以响应的安全问题有很多,这里我们只响应HTTPS相关的就行,因此选择NSURLAuthenticationMethodServerTrust。

    第二个方法是处理验证结果的,这里我这样写会直接忽略证书验证,这里我们可以处理证书的验证策略逻辑。

    我们start connection后就会发现可以成功的调用接口了。

    关于一些其他细节

    写这个小玩意还是用到了一些没有接触过的东西的。

    下面总结一下。

    1.文件实例类NSFileHandle,这个类可以拿到文件实例,比如我们想去控制文件读写细节就需要用到这个类,这里使用是为了保存没有成功请求的图片名称。

    2.connection的异步请求做的非常好了,使用多线程请求,具体的请求线程个数由系统来判断。

    3.多线程读写文件使用dispatch_barrier_async方法避免资源竞争。

     

    不足

    1.写的时候是所有上传请求全部结束后才开始下载的,这样效率很低,可以修改为成功上传后就直接下载不用等待其他的文件上传,不过这样多线程处理会稍微麻烦一些。

  • 相关阅读:
    我的第一个作业
    团队任务3:第一次冲刺
    课后作业3:个人项目(词频统计及其效能分析)
    课后作业2:个人项目
    一切的开始,从未有过的改变——课后作业1:准备
    Fiddler 添加IP显示、响应时间功能
    Jmeter所有结果分析
    云盘资源爬取利器 fmv
    python 中的 sys , os 模块用法总结
    Python 编写登录接口
  • 原文地址:https://www.cnblogs.com/madpanda/p/4838475.html
Copyright © 2011-2022 走看看