Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download large file directly to the specified location #33

Merged
merged 1 commit into from
Mar 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 40 additions & 28 deletions src/Dropbox/Dropbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,27 +227,31 @@ public function setAccessToken($accessToken)
/**
* Make Request to the API
*
* @param string $method HTTP Request Method
* @param string $endpoint API Endpoint to send Request to
* @param string $endpointType Endpoint type ['api'|'content']
* @param array $params Request Query Params
* @param string $accessToken Access Token to send with the Request
* @param string $method HTTP Request Method
* @param string $endpoint API Endpoint to send Request to
* @param string $endpointType Endpoint type ['api'|'content']
* @param array $params Request Query Params
* @param string $accessToken Access Token to send with the Request
* @param DropboxFile $responseFile Save response to the file
*
* @return \Kunnu\Dropbox\DropboxResponse
*
* @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
*/
public function sendRequest($method, $endpoint, $endpointType = 'api', array $params = [], $accessToken = null)
public function sendRequest($method, $endpoint, $endpointType = 'api', array $params = [], $accessToken = null, DropboxFile $responseFile = null)
{
//Access Token
$accessToken = $this->getAccessToken() ? $this->getAccessToken() : $accessToken;

//Make a DropboxRequest object
$request = new DropboxRequest($method, $endpoint, $accessToken, $endpointType, $params);

//Make a DropboxResponse object if a response should be saved to the file
$response = $responseFile ? new DropboxResponseToFile($request, $responseFile) : null;

//Send Request through the DropboxClient
//Fetch and return the Response
return $this->getClient()->sendRequest($request);
return $this->getClient()->sendRequest($request, $response);
}

/**
Expand All @@ -267,15 +271,16 @@ public function postToAPI($endpoint, array $params = [], $accessToken = null)
/**
* Make a HTTP POST Request to the Content endpoint type
*
* @param string $endpoint Content Endpoint to send Request to
* @param array $params Request Query Params
* @param string $accessToken Access Token to send with the Request
* @param string $endpoint Content Endpoint to send Request to
* @param array $params Request Query Params
* @param string $accessToken Access Token to send with the Request
* @param DropboxFile $responseFile Save response to the file
*
* @return \Kunnu\Dropbox\DropboxResponse
*/
public function postToContent($endpoint, array $params = [], $accessToken = null)
public function postToContent($endpoint, array $params = [], $accessToken = null, DropboxFile $responseFile = null)
{
return $this->sendRequest("POST", $endpoint, 'content', $params, $accessToken);
return $this->sendRequest("POST", $endpoint, 'content', $params, $accessToken, $responseFile);
}

/**
Expand All @@ -298,27 +303,30 @@ public function makeModelFromResponse(DropboxResponse $response)
* Make DropboxFile Object
*
* @param string|DropboxFile $dropboxFile DropboxFile object or Path to file
* @param int $maxLength Max Bytes to read from the file
* @param int $offset Seek to specified offset before reading
* @param int $maxLength Max Bytes to read from the file
* @param int $offset Seek to specified offset before reading
* @param string $mode The type of access
*
* @return \Kunnu\Dropbox\DropboxFile
*/
public function makeDropboxFile($dropboxFile, $maxLength = -1, $offset = -1)
public function makeDropboxFile($dropboxFile, $maxLength = null, $offset = null, $mode = DropboxFile::MODE_READ)
{
//Uploading file by file path
if (!$dropboxFile instanceof DropboxFile) {
//File is valid
if (is_file($dropboxFile)) {
//Create a DropboxFile Object
$dropboxFile = new DropboxFile($dropboxFile, $maxLength, $offset);
} else {
//File invalid/doesn't exist
throw new DropboxClientException("File '{$dropboxFile}' is invalid.");
}
//Create a DropboxFile Object
$dropboxFile = new DropboxFile($dropboxFile, $mode);
} elseif ($mode !== $dropboxFile->getMode()) {
//Reopen the file with expected mode
$dropboxFile->close();
$dropboxFile = new DropboxFile($dropboxFile->getFilePath(), $mode);
}

$dropboxFile->setOffset($offset);
$dropboxFile->setMaxLength($maxLength);
if ($offset) {
$dropboxFile->setOffset($offset);
}
if ($maxLength) {
$dropboxFile->setMaxLength($maxLength);
}

//Return the DropboxFile Object
return $dropboxFile;
Expand Down Expand Up @@ -1071,26 +1079,30 @@ public function getThumbnail($path, $size = 'small', $format = 'jpeg')
* Download a File
*
* @param string $path Path to the file you want to download
* @param null|string|DropboxFile $dropboxFile DropboxFile object or Path to target file
*
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-download
*
* @return \Kunnu\Dropbox\Models\File
*/
public function download($path)
public function download($path, $dropboxFile = null)
{
//Path cannot be null
if (is_null($path)) {
throw new DropboxClientException("Path cannot be null.");
}

//Make Dropbox File if target is specified
$dropboxFile = $dropboxFile ? $this->makeDropboxFile($dropboxFile, null, null, DropboxFile::MODE_WRITE) : null;

//Download File
$response = $this->postToContent('/files/download', ['path' => $path]);
$response = $this->postToContent('/files/download', ['path' => $path], null, $dropboxFile);

//Get file metadata from response headers
$metadata = $this->getMetadataFromResponseHeaders($response);

//File Contents
$contents = $response->getBody();
$contents = $dropboxFile ? $this->makeDropboxFile($dropboxFile) : $response->getBody();

//Make and return a File model
return new File($metadata, $contents);
Expand Down
24 changes: 15 additions & 9 deletions src/Dropbox/DropboxClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,33 +137,39 @@ protected function buildUrl($endpoint = '', $type = 'api')
* Send the Request to the Server and return the Response
*
* @param DropboxRequest $request
* @param DropboxResponse $response
*
* @return \Kunnu\Dropbox\DropboxResponse
*
* @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
*/
public function sendRequest(DropboxRequest $request)
public function sendRequest(DropboxRequest $request, DropboxResponse $response = null)
{
//Method
$method = $request->getMethod();

//Prepare Request
list($url, $headers, $requestBody) = $this->prepareRequest($request);

$options = [];
if ($response instanceof DropboxResponseToFile) {
$options['sink'] = $response->getFilePath();
}

//Send the Request to the Server through the HTTP Client
//and fetch the raw response as DropboxRawResponse
$rawResponse = $this->getHttpClient()->send($url, $method, $requestBody, $headers);
$rawResponse = $this->getHttpClient()->send($url, $method, $requestBody, $headers, $options);

//Create DropboxResponse from DropboxRawResponse
$dropboxResponse = new DropboxResponse(
$request,
$rawResponse->getBody(),
$rawResponse->getHttpResponseCode(),
$rawResponse->getHeaders()
);
$response = $response ?: new DropboxResponse($request);
$response->setHttpStatusCode($rawResponse->getHttpResponseCode());
$response->setHeaders($rawResponse->getHeaders());
if (!$response instanceof DropboxResponseToFile) {
$response->setBody($rawResponse->getBody());
}

//Return the DropboxResponse
return $dropboxResponse;
return $response;
}

/**
Expand Down
65 changes: 45 additions & 20 deletions src/Dropbox/DropboxFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
*/
class DropboxFile
{
const MODE_READ = 'r';
const MODE_WRITE = 'w';

/**
* Path of the file to upload
*
Expand All @@ -20,7 +23,7 @@ class DropboxFile
*
* @var int
*/
protected $maxLength;
protected $maxLength = -1;

/**
* Seek to the specified offset before reading.
Expand All @@ -29,7 +32,7 @@ class DropboxFile
*
* @var int
*/
protected $offset;
protected $offset = -1;

/**
* File Stream
Expand All @@ -38,22 +41,23 @@ class DropboxFile
*/
protected $stream;

/**
* The type of access
*
* @var string
*/
protected $mode;

/**
* Create a new DropboxFile instance
*
* @param string $filePath Path of the file to upload
* @param int $maxLength Max Bytes to read from the file
* @param int $offset Seek to specified offset before reading
*
* @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
* @param string $mode The type of access
*/
public function __construct($filePath, $maxLength = -1, $offset = -1)
public function __construct($filePath, $mode = self::MODE_READ)
{
$this->path = $filePath;
$this->maxLength = $maxLength;
$this->offset = $offset;

$this->open();
$this->mode = $mode;
}

/**
Expand Down Expand Up @@ -95,11 +99,16 @@ public function setMaxLength($maxLength)
*/
public function open()
{
if (!$this->isRemoteFile($this->path) && !is_readable($this->path)) {
throw new DropboxClientException('Failed to create DropboxFile instance. Unable to read resource: ' . $this->path . '.');
if (!$this->isRemoteFile($this->path)) {
if (self::MODE_READ === $this->mode && !is_readable($this->path)) {
throw new DropboxClientException('Failed to create DropboxFile instance. Unable to read resource: ' . $this->path . '.');
}
if (self::MODE_WRITE === $this->mode && file_exists($this->path) && !is_writable($this->path)) {
throw new DropboxClientException('Failed to create DropboxFile instance. Unable to write resource: ' . $this->path . '.');
}
}

$this->stream = \GuzzleHttp\Psr7\stream_for(fopen($this->path, 'r'));
$this->stream = \GuzzleHttp\Psr7\stream_for(fopen($this->path, $this->mode));

if (!$this->stream) {
throw new DropboxClientException('Failed to create DropboxFile instance. Unable to open resource: ' . $this->path . '.');
Expand All @@ -109,10 +118,13 @@ public function open()
/**
* Get the Open File Stream
*
* @return GuzzleHttp\Psr7\Stream
* @return \GuzzleHttp\Psr7\Stream
*/
public function getStream()
{
if (!$this->stream) {
$this->open();
}
return $this->stream;
}

Expand All @@ -121,7 +133,9 @@ public function getStream()
*/
public function close()
{
$this->stream->close();
if ($this->stream) {
$this->stream->close();
}
}

/**
Expand All @@ -131,19 +145,20 @@ public function close()
*/
public function getContents()
{
$stream = $this->getStream();
// If an offset is provided
if ($this->offset !== -1) {
// Seek to the offset
$this->stream->seek($this->offset);
$stream->seek($this->offset);
}

// If a max length is provided
if ($this->maxLength !== -1) {
// Read from the offset till the maxLength
return $this->stream->read($this->maxLength);
return $stream->read($this->maxLength);
}

return $this->stream->getContents();
return $stream->getContents();
}

/**
Expand All @@ -166,14 +181,24 @@ public function getFilePath()
return $this->path;
}

/**
* Get the mode of the file stream
*
* @return string
*/
public function getMode()
{
return $this->mode;
}

/**
* Get the size of the file
*
* @return int
*/
public function getSize()
{
return $this->stream->getSize();
return $this->getStream()->getSize();
}

/**
Expand Down
Loading