个人小站

最新碎语:你好三月

您的位置:个人小站 >文章> 和风天气接口返回的gzip格式数据解析--esp32--espidf

和风天气接口返回的gzip格式数据解析--esp32--espidf

使用zlib库

下载zlib源码,https://github.com/madler/zlib

espidf工程components文件夹下新建zlib文件夹,解压上面下载的源码到zlib文件夹,新建CMakeList.txt文件。

完成后目录如下图:

QQ截图20230414171244.png

编辑CMakeList.txt文件如下:


idf_component_register(SRCS "zlib/adler32.c" "zlib/crc32.c" "zlib/infback.c" "zlib/inffast.c"
                            "zlib/inflate.c" "zlib/inftrees.c" "zlib/zutil.c"
                       INCLUDE_DIRS zlib
)
从http响应中获取gzip数据长度,http响应如下图


QQ截图20230414171801.png

可以通过headers中的键以及'\r\n'等标志截取来获取content-length数据长度,具体代码就不贴了。

然后获取gzip数据长度后,就可以使用下面的解压缩函数来解压数据流。

gzip解压缩函数如下:


/**
 * pSrc: http返回的gzip数据
 * srcSize: http返回gzip数据长度
 * pOutDest: 解压后数据缓存区地址,malloc申请内存空间
 * pOutBufSize: 缓存区大小
 */
int vidpeek_uncompressGzip(unsigned char *pSrc, unsigned int srcSize, char **pOutDest, unsigned int *pOutBufSize)
{

#define OK 0
#define ERR -1

    int ret = OK;
    char *pBuf = (char *)pSrc + (srcSize - 1);
    unsigned int len = *pBuf;
    int uncompressResult;
    z_stream d_stream;
    int i = 0;

    // check gz file,rfc1952 P6
    if ((*pSrc != 0x1f) || (*(pSrc + 1) != 0x8b))
    {
        return ERR;
    }

    for (i = 0; i < 3; i++)

    {
        pBuf--;
        len <<= 8;
        len += *pBuf;
    }

    // fortest
    if ((len == 0) || (len > 1000000))
    {
        return ERR;
    }

    // gzipdecompression start!!!
    d_stream.zalloc = Z_NULL;
    d_stream.zfree = Z_NULL;
    d_stream.opaque = Z_NULL;
    d_stream.next_in = Z_NULL;
    d_stream.avail_in = 0;

    uncompressResult = inflateInit2(&d_stream, 47);

    if (uncompressResult != Z_OK)
    {
        return uncompressResult;
    }

    d_stream.next_in = pSrc;
    d_stream.avail_in = srcSize;
    d_stream.next_out = (unsigned char *)*pOutDest;
    d_stream.avail_out = len;
    uncompressResult = inflate(&d_stream, Z_NO_FLUSH);

    switch (uncompressResult)
    {
    case Z_NEED_DICT:
        uncompressResult = Z_DATA_ERROR;
    case Z_DATA_ERROR:
    case Z_MEM_ERROR:
        (void)inflateEnd(&d_stream);
        return uncompressResult;
    }

    inflateEnd(&d_stream);
    *pOutBufSize = len - 2;
    return ret;
}


函数调用如下:


size_t out_len = 0;
char *gzip_out_buff = (char *)malloc(MAX_HTTP_OUTPUT_BUFFER * sizeof(char));
memset(gzip_out_buff, 0x0, MAX_HTTP_OUTPUT_BUFFER);

//in_buff即为上面根据http响应获取到的gzip数据流
//len为根据content-length获取的gzip数据长度
vidpeek_uncompressGzip(in_buff, len, &gzip_out_buff, &out_len);


解压缩后就可以使用cJson来解析了。

注:其实get请求时可以使用&gzip=n来避免返回gzip数据,不过次数多了好像就不管用了

参考文章:

https://yuanze.wang/posts/esp32-unzip-gzip-http-response/

https://blog.csdn.net/weixin_28607671/article/details/116988589

---

转载请注明本文标题和链接:《和风天气接口返回的gzip格式数据解析--esp32--espidf

发表评论

路人甲 表情
看不清楚?点图切换 Ctrl+Enter快速提交