一聚教程网:一个值得你收藏的教程网站

热门教程

Swift使用gzip压缩NSData数据(附:请求时将JSON数据进行压缩)

时间:2022-06-25 23:40:46 编辑:袖梨 来源:一聚教程网

GZIP 是为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。使用 GZIP 一来可以减少存储空间,二来通过网络传输文件时,可以减少传输的时间。
大流量的WEB站点常常使用GZIP压缩技术,将网页内容压缩后传输到来访的电脑浏览器中显示出来(一般对纯文本内容可压缩到原大小的40%),大大提高了传输速度。
在iOS开发中,我们客户端也是可以利用 GZIP 来进行数据压缩的,比如网络请求时,将数据量比较大的参数进行压缩再传输,可以节约流量,提高速度。

一,使用gzip压缩NSData数据

为方便操作,我们可以使用 NSData+GZIP.swift 这个第三方扩展类(内部使用的是 zlib 库)。它对 NSData 进行了扩展,使其支持gzip压缩与解压缩。
GitHub地址:https://github.com/1024jp/NSData-GZIP

1,配置说明

(1)在Build Phases -> Link Binary With Libraries中点击加号,添加 libz.tbd 到项目中来
原文:Swift - 使用gzip压缩NSData数据(附:请求时将JSON数据进行压缩)

(2)创建桥接头文件 bridge.h,将 zlib 库引用进来
1
#include
(3)将下载下来的 NSData+GZIP.swift 添加到项目中。把其中的 import zlib 给去掉。
1
//import zlib

2,使用样例

对任何数据进行gzip的压缩都要先将其转换成 NSData 类型,下面提供几个样例大家可以比较下压缩效率。
(1)字符串的压缩与解压缩


let str = "欢迎来到www.111com.net 。航歌,做最好的开放者知识平台。欢迎来到www.111com.net 。航歌,做最好的开放者知识平台。欢迎来到www.111com.net 。航歌,做最好的开放者知识平台。欢迎来到www.111com.net 。"
 
//原始数据
let data:NSData = str.dataUsingEncoding(NSUTF8StringEncoding)!
print("压缩前的大小:(data.length)字节")
 
//压缩后数据
let compressedData:NSData = try! data.gzippedData()
print("压缩后的大小:(compressedData.length)字节")
 
//解压缩
let originalData = try! compressedData.gunzippedData()
let originalStr:String = NSString(data: originalData,
    encoding: NSUTF8StringEncoding) as! String
原文:Swift - 使用gzip压缩NSData数据(附:请求时将JSON数据进行压缩)

(2)JSON数据的压缩与解压缩

let parameters = [
    "name":"hangge",
    "age":10,
    "score":98.5,
    "phones":[123,442,432,132,444],
    "numbers":[10,87,69,99,93,123,123],
    "address":"中华人民共和国",
    "slogan":"www.111com.net  - 做最好的开发者知识平台",
    "others":[
        ["paramName":"a" , "value":99],
        ["paramName":"s" , "value":77],
        ["paramName":"v" , "value":87],
        ["paramName":"t" , "value":99]
    ]
]
 
//原始数据
let data = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
print("压缩前的大小:(data.length)字节")
 
//压缩后数据
let compressedData:NSData = try! data.gzippedData()
print("压缩后的大小:(compressedData.length)字节")
 
//解压缩
let originalData = try! compressedData.gunzippedData()
let originalJSON:AnyObject! = try? NSJSONSerialization
    .JSONObjectWithData(data, options:.AllowFragments)

 

(3)文件的压缩与解压缩


let path = NSBundle.mainBundle().pathForResource("readme", ofType: "txt")!
 
//原始数据
let data = NSData(contentsOfFile: path)!
print("压缩前的大小:(data.length)字节")
 
//压缩后数据
let compressedData:NSData = try! data.gzippedData()
print("压缩后的大小:(compressedData.length)字节")
 
//解压缩
let originalData = try! compressedData.gunzippedData()

二,网络请求时,使用gzip压缩发送的JSON数据

这里以使用 Alamofire 这个网络库为例,详细的配置和使用方法可以看我原来写的文章(Swift - HTTP网络操作库Alamofire使用详解)
假设我们有如下的数据要发送:


let params = [
    "name": "www.111com.net ",
    "books": ["Swift","Objective-C","PHP"],
    "bar": [
        "baz": "qux"
    ]
]
Alamofire支持将参数使用 JSON 格式编码进行传输:

Alamofire.request(.POST, "http://www.111com.net /json.php", parameters: params, encoding: .JSON)
但它不支持gzip压缩,我们可以使用自定义(Custom)的编码方式来实现。

1,首先,定义一个实现gzip压缩的自定义编码方式


let gzipEncoding = ParameterEncoding.Custom { request, parameters in
    
    let jsonEncoding = Alamofire.ParameterEncoding.JSON
    let (jsonEncodedRequest, _) = jsonEncoding.encode(request, parameters: parameters)
    let mutableRequest = jsonEncodedRequest.mutableCopy() as! NSMutableURLRequest
    
    var gzipEncodingError: NSError? = nil
    
    do {
        let gzippedData = try mutableRequest.HTTPBody?.gzippedData()
        mutableRequest.HTTPBody = gzippedData
        
        if mutableRequest.HTTPBody != nil {
            mutableRequest.setValue("gzip", forHTTPHeaderField: "Content-Encoding")
        }
    } catch {
        gzipEncodingError = error as NSError
    }
    
    return (mutableRequest, gzipEncodingError)
}

2,使用gzip编码方式发送数据


let url = "http://www.111com.net /json.php"
Alamofire.request(.POST, url , parameters: params, encoding: gzipEncoding)
    .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,客户端收到的返回消息如下,说明服务端正常接收并解析了数据。

 

热门栏目