/** * Загрузить файл на диск * * @param string $file_path может быть как путь к локальному файлу, так и URL к файлу * @param mixed $overwrite * @param mixed $progress * @return boolean * @throws mixed */ public function upload($file_path, $overwrite = false, $progress = null) { if (!is_string($file_path)) { throw new \InvalidArgumentException('Параметр "путь к файлу" должен быть строкового типа.'); } $scheme = substr($file_path, 0, 7); if ($scheme == 'http://' or $scheme == 'https:/') { try { $response = $this->request->post($this->parent_disk->getRequestUrl('resources/upload', array('url' => $file_path, 'path' => $this->resource_path))); } catch (AlreadyExistsException $exc) { // параметр $overwrite не работает т.к. диск не поддерживает {AlreadyExistsException:409}->rename->delete throw new AlreadyExistsException($exc->getMessage() . ' Перезапись для удалённой загрузки не доступна.', $exc->getCode(), $exc); } if (!empty($response['operation'])) { return $response['operation']; } return false; } if (!is_file($file_path)) { throw new \OutOfBoundsException('Локальный файл по такому пути: "' . $file_path . '" отсутствует.'); } if ($overwrite instanceof \Closure) { $progress = $overwrite; $overwrite = false; } $access_upload = $this->request->get($this->parent_disk->getRequestUrl('resources/upload', array('path' => $this->resource_path, 'overwrite' => (int) (bool) $overwrite))); if (!isset($access_upload['href'])) { throw new \RuntimeException('Не возможно загрузить локальный файл - не получено разрешение.'); } if ($progress instanceof \Closure) { $this->request->progress(function ($curl, $download, $downloaded, $upload, $uploaded) use($progress) { return $progress($upload, $uploaded, $curl); }); } $put_data = null; $file_path = realpath($file_path); $this->request->setTimeout(null); $this->request->unsetHeader('Content-Type'); $this->request->unsetHeader('Content-Length'); $this->request->setOpt(CURLOPT_INFILESIZE, filesize($file_path)); if ($this->encryption()) { /* Ограничение. Ограничение на длину объекта custom_properties (имена и значения вложенных ключей, а также синтаксические знаки) — 1024 символа. */ $put_data = ['']; $this->request->setOpt(CURLOPT_UPLOAD, true); $this->request->setOpt(CURLOPT_BINARYTRANSFER, true); $this->request->setOpt(CURLOPT_INFILE, fopen($file_path, 'rb')); $this->request->setOpt(CURLOPT_READFUNCTION, function ($ch, $fh, $length) use(&$block_length) { try { return $this->encrypt(fread($fh, $block_length = $length), true); } catch (\Exception $exc) { return; } }); } $this->request->put($access_upload['href'], $put_data ?: ['file' => new \CurlFile($file_path)]); $this->request->setOpt(CURLOPT_INFILESIZE, null); $this->request->setHeader('Content-Type', $this->parent_disk->contentType()); $this->request->setDefaultTimeout(); $this->request->progress(null); $this->request->setOpt(CURLOPT_NOPROGRESS, true); $result = $this->request->http_status_code; if ($this->encryption()) { $this->request->setOpt([CURLOPT_UPLOAD => false, CURLOPT_BINARYTRANSFER => false, CURLOPT_INFILE => null, CURLOPT_READFUNCTION => null]); $this->set(['encrypted' => md5_file($file_path), 'encrypted_block' => $block_length, 'encrypted_phrase' => (string) $this->phrase(), 'encrypted_vector' => base64_encode($this->vector(false))]); } return $result == 201; }