關於獲取http的gzip內容並解壓
阿新 • • 發佈:2018-12-27
網上很多程式碼,都是以下的程式碼。我自己用SOCKET實現的時候(呼叫ZLIB庫),發現都是可以的。
int inflate_read(char *source,int len,char **dest,int gzip)
{ int ret; unsigned have; z_stream strm; unsigned char out[CHUNK]; int totalsize = 0; /* allocate inflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; if (gzip) ret = inflateInit2(&strm, 47); else ret = inflateInit(&strm); if (ret != Z_OK) return ret; strm.avail_in = len; strm.next_in = source; /* run inflate() on input until output buffer not full */ do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate(&strm, Z_NO_FLUSH); assert(ret != Z_STREAM_ERROR); /* state not clobbered */ switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd(&strm); return ret; } have = CHUNK - strm.avail_out; totalsize += have; *dest = realloc(*dest,totalsize); memcpy(*dest + totalsize - have,out,have); } while (strm.avail_out == 0); /* clean up and return */ (void)inflateEnd(&strm); return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; }
而昨天用在WININET的返回資料裡面的時候,發現不行。於是去搜索資料,參考了一些資料之後,發現WININET添加了gzip的頭部,於是自己參考了
https://github.com/wkoszek/mini_gzip
寫了一個函式。並且,miniz.c的程式碼裡面和zlib的略不同,需要把上面一個函式的47修改成 -MZ_DEFAULT_WINDOW_BITS。
int mini_gz_get_data_offset(const unsigned char *buffer, int bufferlength) { int offset; int result = 0; if (10 < bufferlength) { buffer + 0; // .gz header if (buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08) { // auxillary header offset = 10; if (buffer[3] & 0x4) { //fextra_len = buffer[offset + 1] << 8 | buffer[offset + 0]; offset += 2; //fextra_ptr = &buffer[offset]; } if (buffer[3] & 0x8) { //fname_ptr = &buffer[offset]; while (buffer[offset++] != '\0') { ; } } if (buffer[3] & 0x10) { //fcomment_ptr = &buffer[offset]; while (buffer[offset++] != '\0') { ; } } if (buffer[3] & 0x2) { //fcrc = *(unsigned short *)&buffer[offset]; offset += 2; } result = offset; } } return (result); }
希望後來的人可以少走彎路。