Etag.php 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <?php
  2. namespace Qiniu;
  3. use Qiniu\Config;
  4. final class Etag
  5. {
  6. private static function packArray($v, $a)
  7. {
  8. return call_user_func_array('pack', array_merge(array($v), (array)$a));
  9. }
  10. private static function blockCount($fsize)
  11. {
  12. return intval(($fsize + (Config::BLOCK_SIZE - 1)) / Config::BLOCK_SIZE);
  13. }
  14. private static function calcSha1($data)
  15. {
  16. $sha1Str = sha1($data, true);
  17. $err = error_get_last();
  18. if ($err !== null) {
  19. return array(null, $err);
  20. }
  21. $byteArray = unpack('C*', $sha1Str);
  22. return array($byteArray, null);
  23. }
  24. public static function sum($filename)
  25. {
  26. $fhandler = fopen($filename, 'r');
  27. $err = error_get_last();
  28. if ($err !== null) {
  29. return array(null, $err);
  30. }
  31. $fstat = fstat($fhandler);
  32. $fsize = $fstat['size'];
  33. if ((int)$fsize === 0) {
  34. fclose($fhandler);
  35. return array('Fto5o-5ea0sNMlW_75VgGJCv2AcJ', null);
  36. }
  37. $blockCnt = self::blockCount($fsize);
  38. $sha1Buf = array();
  39. if ($blockCnt <= 1) {
  40. array_push($sha1Buf, 0x16);
  41. $fdata = fread($fhandler, Config::BLOCK_SIZE);
  42. if ($err !== null) {
  43. fclose($fhandler);
  44. return array(null, $err);
  45. }
  46. list($sha1Code,) = self::calcSha1($fdata);
  47. $sha1Buf = array_merge($sha1Buf, $sha1Code);
  48. } else {
  49. array_push($sha1Buf, 0x96);
  50. $sha1BlockBuf = array();
  51. for ($i = 0; $i < $blockCnt; $i++) {
  52. $fdata = fread($fhandler, Config::BLOCK_SIZE);
  53. list($sha1Code, $err) = self::calcSha1($fdata);
  54. if ($err !== null) {
  55. fclose($fhandler);
  56. return array(null, $err);
  57. }
  58. $sha1BlockBuf = array_merge($sha1BlockBuf, $sha1Code);
  59. }
  60. $tmpData = self::packArray('C*', $sha1BlockBuf);
  61. list($sha1Final,) = self::calcSha1($tmpData);
  62. $sha1Buf = array_merge($sha1Buf, $sha1Final);
  63. }
  64. $etag = \Qiniu\base64_urlSafeEncode(self::packArray('C*', $sha1Buf));
  65. return array($etag, null);
  66. }
  67. }