1. 网络请求request类:
.h 头文件:
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
@interface GZipRequestSerializer : AFJSONRequestSerializer
@end
.m 实现文件:
#import "GZipRequestSerializer.h"
#import "GzipTool.h"
@implementation GZipRequestSerializer
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSMutableURLRequest *mutableRequest = [super requestBySerializingRequest:request withParameters:parameters error:error].mutableCopy;
// 追加 gzip 头
NSAssert([mutableRequest valueForHTTPHeaderField:@"Content-Encoding"], @"gzip时 Content-Encoding 被占用");
[mutableRequest setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
NSData *paramsData = [NSJSONSerialization dataWithJSONObject:parameters options:kNilOptions error:nil];
paramsData = [GzipTool toGZipCompressData:paramsData];
[mutableRequest setHTTPBody:paramsData];
return mutableRequest;
}
@end
2. 压缩类
.h 头文件:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface GzipTool : NSObject
/**
* GZip压缩数据
* @param aUnData 未压缩数据
* @return 已压缩数据
*/
+ (NSData *)toGZipCompressData:(NSData *)aUnData;
/**
* GZip解压数据
* @param compressedData 压缩数据
* @return 解压缩数据
*/
+ (NSData *)unCompressZippedData:(NSData *)compressedData;
@end
NS_ASSUME_NONNULL_END
.m 实现文件:
#import "GzipTool.h"
#import "zlib.h"
@implementation GzipTool
/*GZip压缩数据*/
+ (NSData *)toGZipCompressData:(NSData *)aUnData {
if (![aUnData isKindOfClass:[NSData class]]) {
return nil;
}
@try {
if (aUnData.length == 0 || [self isGzippedData:aUnData]) {
return aUnData;
}
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = (uint) aUnData.length;
stream.next_in = (Bytef *) (void *) aUnData.bytes;
stream.total_out = 0;
stream.avail_out = 0;
static const NSUInteger ChunkSize = 16384;
NSMutableData *output = nil;
if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
output = [NSMutableData dataWithLength:ChunkSize];
while (stream.avail_out == 0) {
if (stream.total_out >= output.length) {
output.length += ChunkSize;
}
stream.next_out = (uint8_t *) output.mutableBytes + stream.total_out;
stream.avail_out = (uInt)(output.length - stream.total_out);
deflate(&stream, Z_FINISH);
}
deflateEnd(&stream);
output.length = stream.total_out;
}
return output;
}
@catch (NSException *exception) {
NSLog(@"gzip error: %@", exception);
return nil;
}
}
+ (NSData *)unCompressZippedData:(NSData *)compressedData
{
if ([compressedData length] == 0) return compressedData;
unsigned long full_length = compressedData.length;
unsigned long half_length = [compressedData length] / 2;
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[compressedData bytes];
strm.avail_in = (uint) [compressedData 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];
}
// chadeltu 加了(Bytef *)
strm.next_out = (Bytef *)[decompressed mutableBytes] + strm.total_out;
strm.avail_out = (uint)(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;
}
}
+ (BOOL)isGzippedData:(NSData *)aData {
const UInt8 *bytes = (const UInt8 *) aData.bytes;
return (aData.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
}
@end