Swift - 使用gzip压缩Data数据(附:请求时将JSON数据进行压缩)
GZIP 是为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。使用 GZIP 一来可以减少存储空间,二来通过网络传输文件时,可以减少传输的时间。
大流量的WEB站点常常使用GZIP压缩技术,将网页内容压缩后传输到来访的电脑浏览器中显示出来(一般对纯文本内容可压缩到原大小的40%),大大提高了传输速度。
在iOS开发中,我们客户端也是可以利用 GZIP 来进行数据压缩的,比如网络请求时,将数据量比较大的参数进行压缩再传输,可以节约流量,提高速度。
一,使用gzip压缩Data数据
为方便操作,我们可以使用 Data+GZIP.swift 这个第三方扩展类(内部使用的是 zlib 库)。它对 Data 进行了扩展,使其支持gzip压缩与解压缩。
GitHub地址:https://github.com/1024jp/GzipSwift
1,配置说明
(1)在Build Phases -> Link Binary With Libraries中点击加号,添加 libz.tbd 到项目中来
(2)创建桥接头文件 bridge.h,将 zlib 库引用进来
2,使用样例
对任何数据进行gzip的压缩都要先将其转换成 Data 类型,下面提供几个样例大家可以比较下压缩效率。
(1)字符串的压缩与解压缩
(2)JSON数据的压缩与解压缩
(3)文件的压缩与解压缩
二,网络请求时,使用gzip压缩发送的JSON数据
这里以使用 Alamofire 这个网络库为例,详细的配置和使用方法可以看我原来写的文章(Swift - HTTP网络操作库Alamofire使用详解)
假设我们有如下的数据要发送:
1,首先,定义一个实现json格式的gzip压缩的自定义编码方式
2,使用gzip编码方式发送数据
3,服务端接收页面(json.php)代码
4,客户端收到的返回消息如下,说明服务端正常接收并解析了数据。
大流量的WEB站点常常使用GZIP压缩技术,将网页内容压缩后传输到来访的电脑浏览器中显示出来(一般对纯文本内容可压缩到原大小的40%),大大提高了传输速度。
在iOS开发中,我们客户端也是可以利用 GZIP 来进行数据压缩的,比如网络请求时,将数据量比较大的参数进行压缩再传输,可以节约流量,提高速度。
一,使用gzip压缩Data数据
为方便操作,我们可以使用 Data+GZIP.swift 这个第三方扩展类(内部使用的是 zlib 库)。它对 Data 进行了扩展,使其支持gzip压缩与解压缩。
GitHub地址:https://github.com/1024jp/GzipSwift
1,配置说明
(1)在Build Phases -> Link Binary With Libraries中点击加号,添加 libz.tbd 到项目中来
(2)创建桥接头文件 bridge.h,将 zlib 库引用进来
#include <zlib.h>(3)将下载下来的 Data+GZIP.swift 添加到项目中。把其中的 import zlib 给去掉。
//import zlib
2,使用样例
对任何数据进行gzip的压缩都要先将其转换成 Data 类型,下面提供几个样例大家可以比较下压缩效率。
(1)字符串的压缩与解压缩
let str = "欢迎来到hangge.com。航歌,做最好的开放者知识平台。欢迎来到hangge.com。航歌,做最好的开放者知识平台。欢迎来到hangge.com。航歌,做最好的开放者知识平台。欢迎来到hangge.com。" //原始数据 let data = str.data(using: String.Encoding.utf8)! print("压缩前的大小:\(data.count)字节") //压缩后数据 let compressedData = try! data.gzipped() print("压缩后的大小:\(compressedData.count)字节") //解压缩 let originalData = try! compressedData.gunzipped() let originalStr = String(data: originalData, encoding: String.Encoding.utf8)
(2)JSON数据的压缩与解压缩
let parameters:[String : Any] = [ "name":"hangge", "age":10, "score":98.5, "phones":[123,442,432,132,444], "numbers":[10,87,69,99,93,123,123], "address":"中华人民共和国", "slogan":"hangge.com - 做最好的开发者知识平台", "others":[ ["paramName":"a" , "value":99], ["paramName":"s" , "value":77], ["paramName":"v" , "value":87], ["paramName":"t" , "value":99] ] ] //原始数据 let data = try! JSONSerialization.data(withJSONObject: parameters, options: []) print("压缩前的大小:\(data.count)字节") //压缩后数据 let compressedData = try! data.gzipped() print("压缩后的大小:\(compressedData.count)字节") //解压缩 let originalData = try! compressedData.gunzipped() let originalJSON = try? JSONSerialization .jsonObject(with: originalData, options:.allowFragments)
(3)文件的压缩与解压缩
let path = Bundle.main.path(forResource: "readme", ofType: "txt")! let url = URL(fileURLWithPath: path) //原始数据 let data = try! Data(contentsOf: url) print("压缩前的大小:\(data.count)字节") //压缩后数据 let compressedData = try! data.gzipped() print("压缩后的大小:\(compressedData.count)字节") //解压缩 let originalData = try! compressedData.gunzipped()
二,网络请求时,使用gzip压缩发送的JSON数据
这里以使用 Alamofire 这个网络库为例,详细的配置和使用方法可以看我原来写的文章(Swift - HTTP网络操作库Alamofire使用详解)
假设我们有如下的数据要发送:
let params:[String : Any] = [ "name": "hangge.com", "books": ["Swift","Objective-C","PHP"], "bar": [ "baz": "qux" ] ]Alamofire支持将参数使用 JSON 格式编码进行传输:
let url = "http://www.hangge.com/json.php" Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default)但它不支持gzip压缩,我们可以使用自定义(Custom)的编码方式来实现。
1,首先,定义一个实现json格式的gzip压缩的自定义编码方式
struct JSONGzipEncoding: ParameterEncoding { //返回一个`JSONGzipEncoding`实例对象 public static var `default`: JSONGzipEncoding { return JSONGzipEncoding() } //实现编码方法 func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { var urlRequest = urlRequest.urlRequest! //首先进行json编码 urlRequest = try JSONEncoding().encode(urlRequest, with: parameters) //再进行gzip压缩 let gzippedData = try urlRequest.httpBody?.gzipped() urlRequest.httpBody = gzippedData if urlRequest.httpBody != nil { urlRequest.setValue("gzip", forHTTPHeaderField: "Content-Encoding") } return urlRequest } }
2,使用gzip编码方式发送数据
let url = "http://hangge.com/json.php" Alamofire.request(url, method: .post, parameters: params, encoding: JSONGzipEncoding.default) .responseString { response in print(response.result.value!) }
3,服务端接收页面(json.php)代码
<? $gunzip = gzdecode(file_get_contents("php://input")); $postdata = json_decode($gunzip,TRUE); echo "收到的书籍有:"; $books= $postdata["books"]; foreach ($books as $book){ echo $book."|"; } ?>
4,客户端收到的返回消息如下,说明服务端正常接收并解析了数据。
5,源码下载
hangge_1032.zip(2016-01-25 Swift2)
hangge_1032.zip(2016-09-21 Swift3 最新版)
http://hangge.com/json.php 航哥,你的这个json类网址没有数据,望关注一下这个问题,这样对这个用法能了解的比较通点
感谢!持续关注中....