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 fd66e34bd2d8..41134511b80a 100644 --- a/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php +++ b/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php @@ -196,7 +196,7 @@ private function getOAuthBaseParams() { * @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 3c4022f24ce5..f59b5a460e1d 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 @@ public function __construct($params) { ) { $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 @@ public function fopen($path, $mode) { 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);