From 443d72ee87fa1b67863d5666f2fcd4eb3dc7b390 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);