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 <zlib.h>
(3)將下載下來的 NSData+GZIP.swift 添加到項目中。把其中的 import zlib 給去掉。
1
//import zlib
2,使用樣例
對任何數據進行gzip的壓縮都要先將其轉換成 NSData 類型,下面提供幾個樣例大家可以比較下壓縮效率。
(1)字符串的壓縮與解壓縮
let str = "歡迎來到www.111cn.net 。航歌,做最好的開放者知識平台。歡迎來到www.111cn.net 。航歌,做最好的開放者知識平台。歡迎來到www.111cn.net 。航歌,做最好的開放者知識平台。歡迎來到www.111cn.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.111cn.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.111cn.net ",
"books": ["Swift","Objective-C","PHP"],
"bar": [
"baz": "qux"
]
]
Alamofire支持將參數使用 JSON 格式編碼進行傳輸:
Alamofire.request(.POST, "http://www.111cn.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.111cn.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,客戶端收到的返回消息如下,說明服務端正常接收並解析了數據。