天天看點

iOS與Java伺服器GZip壓縮問題

昨天搞了一天的gzip壓縮,試了三種方式(libz庫,ziparchive,asihttprequest),一開始都不成功。理論上三個應該都能用的,但我都不行。等我試到第三種方式的時候才知道,不是我的問題,而是背景的問題(java端輸出方式一會再說)。今天就總結一下,寫寫ios與java伺服器擷取壓縮資料的方法吧。一、用戶端-服務端資料壓縮解壓流程(asihttprequest)用戶端生成request,設定header允許使用壓縮("accept-encoding","gzip"),即是告訴伺服器,用戶端支援壓縮,但凡可以壓縮的伺服器,盡管來吧!伺服器收到這個header,如果它支援壓縮,可以通過壓縮方式輸出資料,然後再寫入response的header("content-encoding","gzip")

1.以asihttprequest為例,代碼如下: nsurl* requesturl = [nsurl urlwithstring:_listurl]; asihttprequest *request = [asihttprequest requestwithurl:requesturl]; // 預設為yes, 你可以設定它為no來禁用gzip壓縮 [request setallowcompressedresponse:yes]; [request setdelegate:self]; [request

startasynchronous]; 如果是普通的urlrequest,隻要: request.setheader("accept-encoding","gzip"); 2.伺服器端傳回: response.setheader("content-encoding","gzip"); 3.用戶端響應,同樣以asihttprequest為例(此例傳輸的是json資料,我還使用了sbjson解析一下): - (void)requestfinished:(asihttprequest *)request{ nsstring

*jsonstring = @""; sbjsonparser* jsonparser = [[sbjsonparser alloc] init]; nsmutabledictionary *jsondictionary = nil; bool datawascompressed = [request isresponsecompressed]; // 響應是否被gzip壓縮過? if (datawascompressed) { nsdata *uncompresseddata = [request responsedata];

// 解壓縮後的資料 nsstringencoding enc = cfstringconvertencodingtonsstringencoding(kcfstringencodinggb_18030_2000); jsonstring = [[nsstring alloc]initwithdata:uncompresseddata encoding:enc]; jsondictionary = [jsonparser objectwithstring:jsonstring error:nil]; [jsonstring

release]; } else { jsonstring = [request responsestring]; jsondictionary = [jsonparser objectwithstring:jsonstring error:nil]; } self._tabledict = jsondictionary; [jsonparser release]; [self loadtabledict]; [self release]; } 附上一篇非常詳細的asihttprequest請求json資料教程(無gzip相關内容):

http://ios-blog.co.uk/articles/tutorials/parsing-json-on-ios-with-asihttprequest-and-sbjson/ libz庫 libz庫是官方的一個庫,貌似asihttprequest也是用這個庫解壓的,當我們獲得壓縮過的data資料以後(方法與上面類似,隻是獲得了普通的data資料響應),可以使用這種方法解壓資料,解壓方法如下所示(如果僅僅放在目前類下面使用,傳個data參數進來,然後把self換成變量名): #include @implementation

nsdata (dddata) - (nsdata *)gzipinflate { if ([self length] == 0) return self; unsigned full_length = [self length]; unsigned half_length = [self length] / 2; nsmutabledata *decompressed = [nsmutabledata datawithlength: full_length + half_length]; bool done

= no; int status; z_stream strm; strm.next_in = (bytef *)[self bytes]; strm.avail_in = [self length]; strm.total_out = 0; strm.zalloc = z_null; strm.zfree = z_null; if (inflateinit2(&strm, (15+32)) != z_ok) return nil; while (!done) { // make sure we have

enough room and reset the lengths. if (strm.total_out >= [decompressed length]) [decompressed increaselengthby: half_length]; strm.next_out = [decompressed mutablebytes] + strm.total_out; strm.avail_out = [decompressed length] - strm.total_out; // inflate

another chunk. status = inflate (&strm, z_sync_flush); if (status == z_stream_end) done = yes; else if (status != z_ok) break; } if (inflateend (&strm) != z_ok) return nil; // set real length. if (done) { [decompressed setlength: strm.total_out]; return [nsdata

datawithdata: decompressed]; } else return nil; } 附上一篇非常詳細的libz庫壓縮教程 http://www.clintharris.net/2009/how-to-gzip-data-in-memory-using-objective-c/ 以及壓縮解壓教程(代碼從這裡拷貝的): http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html ziparchive 上面講的都是memory壓縮與解壓,ziparchive主要是對文檔進行處理。昨天在上述方法不成功的情況下,我把擷取的data資料savetofile,然後再處理,理論上是可行的,但是由于伺服器有誤,擷取的資料不對,是以我怎麼都解壓不成功!!!!示例如下:

objective-c class used to zip / unzip compressed zip file. usage: add all the files to you project, and and framework libz.1.2.3.dylib. include ziparchive.h using #import "ziparchive/ziparchive.h" * create zip file ziparchive* zipfile = [[ziparchive alloc]

init]; [zipfile createzipfile2:@"zipfilename"]; // a or [[zipfile createzipfile2:@"zipfilename" password:@"your password"];// if password needed, //empty password will get same result as a [zipfile addfiletozip:@"fullpath of the file" newname:@"new name of

the file without path"]; ....add any number of files here [zipfile closezipfile2]; [zipfile release]; // remember to release the object * unzip compressed file ziparchive* zipfile = [[ziparchive alloc] init]; [zipfile unzipopenfile:@"zip file name"]; // b

(the zip got no password) or [zipfile unzipopenfile:@"zip file name" password:@"password" ]; [zipfile unzipfileto:@"output path" overwrite:yes]; [zipfile unzipclosefile]; [zipfile release];