resumable_io.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. require_once("http.php");
  3. require_once("auth_digest.php");
  4. // ----------------------------------------------------------
  5. // class Qiniu_Rio_PutExtra
  6. class Qiniu_Rio_PutExtra
  7. {
  8. public $Bucket = null; // 必选(未来会没有这个字段)。
  9. public $Params = null;
  10. public $MimeType = null;
  11. public $ChunkSize = 0; // 可选。每次上传的Chunk大小
  12. public $TryTimes = 0; // 可选。尝试次数
  13. public $Progresses = null; // 可选。上传进度:[]BlkputRet
  14. public $Notify = null; // 进度通知:func(blkIdx int, blkSize int, ret *BlkputRet)
  15. public $NotifyErr = null; // 错误通知:func(blkIdx int, blkSize int, err error)
  16. public function __construct($bucket = null) {
  17. $this->Bucket = $bucket;
  18. }
  19. }
  20. // ----------------------------------------------------------
  21. // func Qiniu_Rio_BlockCount
  22. define('QINIU_RIO_BLOCK_BITS', 22);
  23. define('QINIU_RIO_BLOCK_SIZE', 1 << QINIU_RIO_BLOCK_BITS); // 4M
  24. function Qiniu_Rio_BlockCount($fsize) // => $blockCnt
  25. {
  26. return ($fsize + (QINIU_RIO_BLOCK_SIZE - 1)) >> QINIU_RIO_BLOCK_BITS;
  27. }
  28. // ----------------------------------------------------------
  29. // internal func Qiniu_Rio_Mkblock/Mkfile
  30. function Qiniu_Rio_Mkblock($self, $host, $reader, $size) // => ($blkputRet, $err)
  31. {
  32. if (is_resource($reader)) {
  33. $body = fread($reader, $size);
  34. if ($body === false) {
  35. $err = Qiniu_NewError(0, 'fread failed');
  36. return array(null, $err);
  37. }
  38. } else {
  39. list($body, $err) = $reader->Read($size);
  40. if ($err !== null) {
  41. return array(null, $err);
  42. }
  43. }
  44. if (strlen($body) != $size) {
  45. $err = Qiniu_NewError(0, 'fread failed: unexpected eof');
  46. return array(null, $err);
  47. }
  48. $url = $host . '/mkblk/' . $size;
  49. return Qiniu_Client_CallWithForm($self, $url, $body, 'application/octet-stream');
  50. }
  51. function Qiniu_Rio_Mkfile($self, $host, $key, $fsize, $extra) // => ($putRet, $err)
  52. {
  53. $url = $host . '/mkfile/' . $fsize;
  54. if ($key !== null) {
  55. $url .= '/key/' . Qiniu_Encode($key);
  56. }
  57. if (!empty($extra->MimeType)) {
  58. $url .= '/mimeType/' . Qiniu_Encode($extra->MimeType);
  59. }
  60. $ctxs = array();
  61. foreach ($extra->Progresses as $prog) {
  62. $ctxs []= $prog['ctx'];
  63. }
  64. $body = implode(',', $ctxs);
  65. return Qiniu_Client_CallWithForm($self, $url, $body, 'application/octet-stream');
  66. }
  67. // ----------------------------------------------------------
  68. // class Qiniu_Rio_UploadClient
  69. class Qiniu_Rio_UploadClient
  70. {
  71. public $uptoken;
  72. public function __construct($uptoken)
  73. {
  74. $this->uptoken = $uptoken;
  75. }
  76. public function RoundTrip($req) // => ($resp, $error)
  77. {
  78. $token = $this->uptoken;
  79. $req->Header['Authorization'] = "UpToken $token";
  80. return Qiniu_Client_do($req);
  81. }
  82. }
  83. // ----------------------------------------------------------
  84. // class Qiniu_Rio_Put/PutFile
  85. function Qiniu_Rio_Put($upToken, $key, $body, $fsize, $putExtra) // => ($putRet, $err)
  86. {
  87. global $QINIU_UP_HOST;
  88. $self = new Qiniu_Rio_UploadClient($upToken);
  89. $progresses = array();
  90. $uploaded = 0;
  91. while ($uploaded < $fsize) {
  92. if ($fsize < $uploaded + QINIU_RIO_BLOCK_SIZE) {
  93. $bsize = $fsize - $uploaded;
  94. } else {
  95. $bsize = QINIU_RIO_BLOCK_SIZE;
  96. }
  97. list($blkputRet, $err) = Qiniu_Rio_Mkblock($self, $QINIU_UP_HOST, $body, $bsize);
  98. $host = $blkputRet['host'];
  99. $uploaded += $bsize;
  100. $progresses []= $blkputRet;
  101. }
  102. $putExtra->Progresses = $progresses;
  103. return Qiniu_Rio_Mkfile($self, $QINIU_UP_HOST, $key, $fsize, $putExtra);
  104. }
  105. function Qiniu_Rio_PutFile($upToken, $key, $localFile, $putExtra) // => ($putRet, $err)
  106. {
  107. $fp = fopen($localFile, 'rb');
  108. if ($fp === false) {
  109. $err = Qiniu_NewError(0, 'fopen failed');
  110. return array(null, $err);
  111. }
  112. $fi = fstat($fp);
  113. $result = Qiniu_Rio_Put($upToken, $key, $fp, $fi['size'], $putExtra);
  114. fclose($fp);
  115. return $result;
  116. }
  117. // ----------------------------------------------------------