閱讀922 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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相關內容): https://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庫壓縮教程 https://www.clintharris.net/2009/how-to-gzip-data-in-memory-using-objective-c/ 以及壓縮解壓教程(代碼從這裏拷貝的): https://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];

最後更新:2017-04-02 00:06:55

  上一篇:go Chrome 4周歲 時光機帶你穿越
  下一篇:go C++中判斷一個文件是否存在的方法