当前位置: > > > Swift - 使用gzip压缩Data数据(附:请求时将JSON数据进行压缩)

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 库引用进来
#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  最新版)
评论2
  • 2楼
    2017-01-06 15:04
    smartaf

    http://hangge.com/json.php 航哥,你的这个json类网址没有数据,望关注一下这个问题,这样对这个用法能了解的比较通点

    站长回复

    这个地址是我随便写的。我文章中也放有php代码,需要的话你可以找个php环境来测试。

  • 1楼
    2016-01-26 16:33
    Anyz

    感谢!持续关注中....

    站长回复

    不客气^_^