欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

php解压有时会失败

程序员文章站 2022-05-10 23:26:32
...
采集一个网站的数据时,返回的是以chunked编码,gzip压缩的文档,该网站的服务器显示是IIS,。。。

解码chunked没问题,但是解压gzip压缩文档时,偶尔会失败,这样就影响我提取下一组请求连接了。。。

解压10组左右,就会出现解压失败的情况。。

这是解压前的数据:



解压后的数据:


显然在最后一组,解压失败了。。

这是尝试用过的三组方法:
 private function _deCompressData()   {       if($this->is_gzip) {          $this->response_body =  gzinflate(substr($this->response_body,10));           //           //           if($temp = gzdecode($this->response_body)) {//               $this->response_body = $temp;//           } else {//              $this->response_body =  $this->mygzdecode($this->response_body);//           }                     //$this->response_body =  $this->mygzdecode($this->response_body);             //         $this->response_body = gzdecode($this->response_body);       }   }


mygzdecode函数是这一个

 /**    * @desc 自定义解压函数    */   function mygzdecode($data, &$filename = '', &$error = '', $maxlength = null)    {        $len = strlen($data);        if ($len  0) {            switch ($method) {                case 8:                    // Currently the only supported compression method:                    $data = gzinflate($body, $maxlength);                    break;                default:                    $error = "Unknown compression method.";                    return false;            }        }  // zero-byte body content is allowed        // Verifiy CRC32        $crc = sprintf("%u", crc32($data));        $crcOK = $crc == $datacrc;        $lenOK = $isize == strlen($data);        if (!$lenOK || !$crcOK) {            $error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');            return false;        }        return $data;    }



也就是说,连续解压时,会出现解压失败的情况


回复讨论(解决方案)

php 已经提供了 gzdecode 函数
如果你的 php 版本实在很低,没有 gzdecode 函数
那么 php 代码级的 gzdecode 函数是

function gzdecode($data) {   $len = strlen($data);   if ($len  0) {     switch ($method) {       case 8:         // Currently the only supported compression method:         $data = gzinflate($body);         break;       default:         // Unknown compression method         return false;     }   } else {     // I'm not sure if zero-byte body content is allowed.     // Allow it for now...  Do nothing...   }   // Verifiy decompressed size and CRC32:   // NOTE: This may fail with large data sizes depending on how   //       PHP's integer limitations affect strlen() since $isize   //       may be negative for large sizes.   if ($isize != strlen($data) || crc32($data) != $datacrc) {     // Bad format!  Length or CRC doesn't match!     return false;   }   return $data; }

自己对比一下,看看是否是你抄写错了

既然函数会在 传入长度 和 crc32 校验失败时返回假,那么你就应该判断一下再进行下一步工作

php 已经提供了 gzdecode 函数
如果你的 php 版本实在很低,没有 gzdecode 函数
那么 php 代码级的 gzdecode 函数是

function gzdecode($data) {   $len = strlen($data);   if ($len  0) {     switch ($method) {       case 8:         // Currently the only supported compression method:         $data = gzinflate($body);         break;       default:         // Unknown compression method         return false;     }   } else {     // I'm not sure if zero-byte body content is allowed.     // Allow it for now...  Do nothing...   }   // Verifiy decompressed size and CRC32:   // NOTE: This may fail with large data sizes depending on how   //       PHP's integer limitations affect strlen() since $isize   //       may be negative for large sizes.   if ($isize != strlen($data) || crc32($data) != $datacrc) {     // Bad format!  Length or CRC doesn't match!     return false;   }   return $data; }



我的是PHP 5.6 ,
gzinflate(substr($this->response_body,10));

gzdecode($this->response_body)

mygzdecode($this->response_body);

这三种方法都可以用,但都遇到同一个问题,连续解压时,会出现解压失败的问题。


大婶,新年快乐哈

自己对比一下,看看是否是你抄写错了

既然函数会在 传入长度 和 crc32 校验失败时返回假,那么你就应该判断一下再进行下一步工作



好的。

在网络上传输的数据,出现错误是不可避免的,但概率不高
重读一下,通常就可以了

主要是你要有容错策略

自己对比一下,看看是否是你抄写错了

既然函数会在 传入长度 和 crc32 校验失败时返回假,那么你就应该判断一下再进行下一步工作




// Verifiy CRC32
$crc = sprintf("%u", crc32($data));
$crcOK = $crc == $datacrc;
$lenOK = $isize == strlen($data);
if (!$lenOK || !$crcOK) {
$this->status = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');
return false;
}
return $data;
检测出来了,是这里校验失败了。。。


对链接http://www.cnu.cc/works/111706发起请求
Length check FAILED. Checksum FAILED.

在网络上传输的数据,出现错误是不可避免的,但概率不高
重读一下,通常就可以了

主要是你要有容错策略



对。。。 这个地方确实需要加强。。。只做了重置连接,没有对收到数据的完整性做校验。。

在网络上传输的数据,出现错误是不可避免的,但概率不高
重读一下,通常就可以了

主要是你要有容错策略




OK了,连续采集10分钟,没出问题 。。。THX,,摸摸大

传输过程出问题,导致部分数据没有了,而解压失败。

把需要解压的文件加入解压列表,每隔5秒-10秒判断解压文件是否变化,如无变化,则解压,解压失败做标记,继续下一个解压。

传输过程出问题,导致部分数据没有了,而解压失败。