From ab50ba7a585368cb473ab551d54fd9c7b0e69811 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 15 Mar 2016 17:22:16 +0100 Subject: [PATCH] Fix dropbox storage to not store the whole file in memory Since the library can only store the full response in memory on download, we use an alternate client lib and set the correct headers to be able to stream the content to a temp file. --- .../3rdparty/Dropbox/OAuth/Curl.php | 2 +- apps/files_external/lib/dropbox.php | 34 +++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php b/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php index fd66e34bd2d..41134511b80 100644 --- a/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php +++ b/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php @@ -196,7 +196,7 @@ class Dropbox_OAuth_Curl extends Dropbox_OAuth { * @return array Array for request's headers section like * array('Authorization' => 'OAuth ...'); */ - private function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) { + public function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) { $oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams(); // create baseString to encode for the sent parameters diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 3c4022f24ce..f59b5a460e1 100644 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -39,6 +39,7 @@ class Dropbox extends \OC\Files\Storage\Common { private $root; private $id; private $metaData = array(); + private $oauth; private static $tempFiles = array(); @@ -51,10 +52,10 @@ class Dropbox extends \OC\Files\Storage\Common { ) { $this->root = isset($params['root']) ? $params['root'] : ''; $this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $this->root; - $oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']); - $oauth->setToken($params['token'], $params['token_secret']); + $this->oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']); + $this->oauth->setToken($params['token'], $params['token_secret']); // note: Dropbox_API connection is lazy - $this->dropbox = new \Dropbox_API($oauth, 'auto'); + $this->dropbox = new \Dropbox_API($this->oauth, 'auto'); } else { throw new \Exception('Creating \OC\Files\Storage\Dropbox storage failed'); } @@ -248,10 +249,31 @@ class Dropbox extends \OC\Files\Storage\Common { switch ($mode) { case 'r': case 'rb': - $tmpFile = \OCP\Files::tmpFile(); try { - $data = $this->dropbox->getFile($path); - file_put_contents($tmpFile, $data); + // slashes need to stay + $encodedPath = str_replace('%2F', '/', rawurlencode(trim($path, '/'))); + $downloadUrl = 'https://api-content.dropbox.com/1/files/auto/' . $encodedPath; + $headers = $this->oauth->getOAuthHeader($downloadUrl, [], 'GET'); + + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $tmpFile = \OC::$server->getTempManager()->getTemporaryFile(); + $client->get($downloadUrl, [ + 'headers' => $headers, + 'save_to' => $tmpFile, + ]); + } catch (RequestException $e) { + if (!is_null($e->getResponse())) { + if ($e->getResponse()->getStatusCode() === 404) { + return false; + } else { + throw $e; + } + } else { + throw $e; + } + } + return fopen($tmpFile, 'r'); } catch (\Exception $exception) { \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);