PHP の解凍が時々失敗する

WBOY
WBOYオリジナル
2016-06-23 13:20:091490ブラウズ

Web サイトからデータを収集すると、チャンクエンコードされ、gzip 圧縮されたドキュメントが返されます。Web サイトのサーバーは IIS として表示されます。 。 。

チャンクのデコードには問題ありませんが、gzip 圧縮ファイルを解凍するときに失敗することがあり、次のリクエスト接続のセットを抽出する能力に影響します。 。 。

10グループほど解凍すると解凍に失敗します。 。

これは解凍前のデータです:



解凍後のデータ:


明らかに、最後のグループでは解凍が失敗しました。 。

これらは、3 つのグループの方法が試行されました:

 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 < 18 || strcmp(substr($data, 0, 2), "\x1f\x8b")) {            $error = "Not in GZIP format.";            return null;  // Not GZIP format (See RFC 1952)        }        $method = ord(substr($data, 2, 1));  // Compression method        $flags = ord(substr($data, 3, 1));  // Flags        if ($flags & 31 != $flags) {            $error = "Reserved bits not allowed.";            return null;        }        // NOTE: $mtime may be negative (PHP integer limitations)        $mtime = unpack("V", substr($data, 4, 4));        $mtime = $mtime[1];        $xfl = substr($data, 8, 1);        $os = substr($data, 8, 1);        $headerlen = 10;        $extralen = 0;        $extra = "";        if ($flags & 4) {            // 2-byte length prefixed EXTRA data in header            if ($len - $headerlen - 2 < 8) {                return false;  // invalid            }            $extralen = unpack("v", substr($data, 8, 2));            $extralen = $extralen[1];            if ($len - $headerlen - 2 - $extralen < 8) {                return false;  // invalid            }            $extra = substr($data, 10, $extralen);            $headerlen += 2 + $extralen;        }        $filenamelen = 0;        $filename = "";        if ($flags & 8) {            // C-style string            if ($len - $headerlen - 1 < 8) {                return false; // invalid            }            $filenamelen = strpos(substr($data, $headerlen), chr(0));            if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {                return false; // invalid            }            $filename = substr($data, $headerlen, $filenamelen);            $headerlen += $filenamelen + 1;        }        $commentlen = 0;        $comment = "";        if ($flags & 16) {            // C-style string COMMENT data in header            if ($len - $headerlen - 1 < 8) {                return false;    // invalid            }            $commentlen = strpos(substr($data, $headerlen), chr(0));            if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {                return false;    // Invalid header format            }            $comment = substr($data, $headerlen, $commentlen);            $headerlen += $commentlen + 1;        }        $headercrc = "";        if ($flags & 2) {            // 2-bytes (lowest order) of CRC32 on header present            if ($len - $headerlen - 2 < 8) {                return false;    // invalid            }            $calccrc = crc32(substr($data, 0, $headerlen)) & 0xffff;            $headercrc = unpack("v", substr($data, $headerlen, 2));            $headercrc = $headercrc[1];            if ($headercrc != $calccrc) {                $error = "Header checksum failed.";                return false;    // Bad header CRC            }            $headerlen += 2;        }        // GZIP FOOTER        $datacrc = unpack("V", substr($data, -8, 4));        $datacrc = sprintf('%u', $datacrc[1] & 0xFFFFFFFF);        $isize = unpack("V", substr($data, -4));        $isize = $isize[1];        // decompression:        $bodylen = $len - $headerlen - 8;        if ($bodylen < 1) {            // IMPLEMENTATION BUG!            return null;        }        $body = substr($data, $headerlen, $bodylen);        $data = "";        if ($bodylen > 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 関数は非常に役に立ちます

自分で比較して確認してくださいもしそうであれば、コピーが間違っています

入力長とcrc32の検証が失敗した場合、関数はfalseを返すため、次のステップに進む前に判断する必要があります

phpにはgzdecode関数が用意されています
あなたのphpのバージョン本当に非常に低いです、gzdecode 関数はありません
PHP コードレベルの gzdecode 関数は

function gzdecode($data) {   $len = strlen($data);   if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {     return $data;  // Not GZIP format (See RFC 1952)   }   $method = ord(substr($data,2,1));  // Compression method   $flags  = ord(substr($data,3,1));  // Flags   if ($flags & 31 != $flags) {     // Reserved bits are set -- NOT ALLOWED by RFC 1952     return data;   }   // NOTE: $mtime may be negative (PHP integer limitations)   $mtime = unpack("V", substr($data,4,4));   $mtime = $mtime[1];   $xfl   = substr($data,8,1);   $os    = substr($data,8,1);   $headerlen = 10;   $extralen  = 0;   $extra     = "";   if ($flags & 4) {     // 2-byte length prefixed EXTRA data in header     if ($len - $headerlen - 2 < 8) {       return false;    // Invalid format     }     $extralen = unpack("v",substr($data,8,2));     $extralen = $extralen[1];     if ($len - $headerlen - 2 - $extralen < 8) {       return false;    // Invalid format     }     $extra = substr($data,10,$extralen);     $headerlen += 2 + $extralen;   }   $filenamelen = 0;   $filename = "";   if ($flags & 8) {     // C-style string file NAME data in header     if ($len - $headerlen - 1 < 8) {       return false;    // Invalid format     }     $filenamelen = strpos(substr($data,8+$extralen),chr(0));     if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {       return false;    // Invalid format     }     $filename = substr($data,$headerlen,$filenamelen);     $headerlen += $filenamelen + 1;   }   $commentlen = 0;   $comment = "";   if ($flags & 16) {     // C-style string COMMENT data in header     if ($len - $headerlen - 1 < 8) {       return false;    // Invalid format     }     $commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));     if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {       return false;    // Invalid header format     }     $comment = substr($data,$headerlen,$commentlen);     $headerlen += $commentlen + 1;   }   $headercrc = "";   if ($flags & 1) {     // 2-bytes (lowest order) of CRC32 on header present     if ($len - $headerlen - 2 < 8) {       return false;    // Invalid format     }     $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;     $headercrc = unpack("v", substr($data,$headerlen,2));     $headercrc = $headercrc[1];     if ($headercrc != $calccrc) {       return false;    // Bad header CRC     }     $headerlen += 2;   }   // GZIP FOOTER - These be negative due to PHP's limitations   $datacrc = unpack("V",substr($data,-8,4));   $datacrc = $datacrc[1];   $isize = unpack("V",substr($data,-4));   $isize = $isize[1];   // Perform the decompression:   $bodylen = $len-$headerlen-8;   if ($bodylen < 1) {     // This should never happen - IMPLEMENTATION BUG!     return null;   }   $body = substr($data,$headerlen,$bodylen);   $data = "";   if ($bodylen > 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);

3 つの方法はすべて使用できますが、連続して解凍すると、同じ問題が発生します。


明けましておめでとうございます、おばちゃん

間違ってコピーしていないか自分で比較してください

入力長と crc32 の検証が失敗した場合、関数は false を返すため、次のステップに進む前に判断する必要があります



わかりました。

ネットワーク上で送信されるデータにはエラーが避けられませんが、その可能性は高くありません
もう一度読んでください。通常は問題ありません

重要なことは、フォールトトレラントな戦略を立てる必要があるということです

エラーが発生しているかどうかを自分で比較してくださいコピーしたのは間違っていました

入力長とcrc32の検証が失敗した場合、関数はfalseを返すので、次のステップに進む前に判断する必要があります




// CRC32を検証します
$crc = sprintf(" %u", crc32($data));
$crcOK $crc $datacrc ; $lenOK this->status = ( $lenOK ? '' : '長さのチェックに失敗しました。' ) . ($crcOK?'': 'チェックサムが失敗しました。');
はい、検証が失敗しました。 。 。


http://www.cnu.cc/works/111706 へのリンクのリクエストを開始します
長さのチェックに失敗しました
もう一度読んでください。通常は問題ありません

重要なのは、フォールトトレラントな戦略を持つ必要があるということです。


はい。 。 。この場所は本当に強化が必要です。 。 。接続をリセットするだけであり、受信したデータの整合性は検証されません。 。

ネットワーク上で送信されるデータにはエラーが避けられませんが、その可能性は高くありません

もう一度読んでください。通常は問題ありません

重要なのは、フォールトトレラントな戦略を立てる必要があるということです



OK、継続的に収集してください10分、問題ありません。 。 。 THX、

送信プロセス中に問題が発生したため、一部のデータが失われ、解凍に失敗しました。

解凍する必要があるファイルを解凍リストに追加し、解凍されたファイルが変化したかどうかを 5 秒〜 10 秒ごとに確認し、変化がない場合は解凍します。解凍に失敗した場合は、マークを付けて次へ進みます。減圧。

送信処理中に問題が発生したため、データの一部が失われ、解凍に失敗しました。



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。