From 2aefb438439dce970dc280ba2eebb82cff123edd Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 14 Mar 2015 08:28:59 -0700 Subject: [PATCH] Support a file data iteration interface for large files Summary: Ref T7149. A couple diffs down the line, this will let us emit chunked files without doing all the work up front or holding the entire file in RAM. Test Plan: (Some newlines added for clarity.) ``` $ ./bin/files cat F942 ABCDEFGHIJKLMNOPQRSTUVWXYZ $ ./bin/files cat F942 --begin 1 BCDEFGHIJKLMNOPQRSTUVWXYZ $ ./bin/files cat F942 --end 10 ABCDEFGHIJ $ ./bin/files cat F942 --begin 3 --end 5 DE $ ``` Reviewers: btrahan Reviewed By: btrahan Subscribers: joshuaspence, epriestley Maniphest Tasks: T7149 Differential Revision: https://secure.phabricator.com/D12071 --- .../PhabricatorFilesManagementCatWorkflow.php | 18 ++++++++++++- .../files/storage/PhabricatorFile.php | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/applications/files/management/PhabricatorFilesManagementCatWorkflow.php b/src/applications/files/management/PhabricatorFilesManagementCatWorkflow.php index ed354d4a89..896165f585 100644 --- a/src/applications/files/management/PhabricatorFilesManagementCatWorkflow.php +++ b/src/applications/files/management/PhabricatorFilesManagementCatWorkflow.php @@ -10,6 +10,16 @@ final class PhabricatorFilesManagementCatWorkflow pht('Print the contents of a file.')) ->setArguments( array( + array( + 'name' => 'begin', + 'param' => 'bytes', + 'help' => pht('Begin printing at a specific offset.'), + ), + array( + 'name' => 'end', + 'param' => 'bytes', + 'help' => pht('End printing at a specific offset.'), + ), array( 'name' => 'names', 'wildcard' => true, @@ -31,7 +41,13 @@ final class PhabricatorFilesManagementCatWorkflow $file = head($this->loadFilesWithNames($names)); - echo $file->loadFileData(); + $begin = $args->getArg('begin'); + $end = $args->getArg('end'); + + $iterator = $file->getFileDataIterator($begin, $end); + foreach ($iterator as $data) { + echo $data; + } return 0; } diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 446fbbbbe8..2fbcf3a891 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -603,6 +603,31 @@ final class PhabricatorFile extends PhabricatorFileDAO return $data; } + + /** + * Return an iterable which emits file content bytes. + * + * @param int Offset for the start of data. + * @param int Offset for the end of data. + * @return Iterable Iterable object which emits requested data. + */ + public function getFileDataIterator($begin = null, $end = null) { + // The default implementation is trivial and just loads the entire file + // upfront. + $data = $this->loadFileData(); + + if ($begin !== null && $end !== null) { + $data = substr($data, $begin, ($end - $begin)); + } else if ($begin !== null) { + $data = substr($data, $begin); + } else if ($end !== null) { + $data = substr($data, 0, $end); + } + + return array($data); + } + + public function getViewURI() { if (!$this->getPHID()) { throw new Exception(