protected function execute(ConduitAPIRequest $request) { $viewer = $request->getUser(); $hash = $request->getValue('contentHash'); $name = $request->getValue('name'); $view_policy = $request->getValue('viewPolicy'); $length = $request->getValue('contentLength'); $properties = array('name' => $name, 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'isExplicitUpload' => true); $ttl = $request->getValue('deleteAfterEpoch'); if ($ttl) { $properties['ttl'] = $ttl; } $file = null; if ($hash) { $file = PhabricatorFile::newFileFromContentHash($hash, $properties); } if ($hash && !$file) { $chunked_hash = PhabricatorChunkedFileStorageEngine::getChunkedHash($viewer, $hash); $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withContentHashes(array($chunked_hash))->executeOne(); } if (strlen($name) && !$hash && !$file) { if ($length > PhabricatorFileStorageEngine::getChunkThreshold()) { // If we don't have a hash, but this file is large enough to store in // chunks and thus may be resumable, try to find a partially uploaded // file by the same author with the same name and same length. This // allows us to resume uploads in Javascript where we can't efficiently // compute file hashes. $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withAuthorPHIDs(array($viewer->getPHID()))->withNames(array($name))->withLengthBetween($length, $length)->withIsPartial(true)->setLimit(1)->executeOne(); } } if ($file) { return array('upload' => (bool) $file->getIsPartial(), 'filePHID' => $file->getPHID()); } // If there are any non-chunk engines which this file can fit into, // just tell the client to upload the file. $engines = PhabricatorFileStorageEngine::loadStorageEngines($length); if ($engines) { return array('upload' => true, 'filePHID' => null); } // Otherwise, this is a large file and we want to perform a chunked // upload if we have a chunk engine available. $chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines(); if ($chunk_engines) { $chunk_properties = $properties; if ($hash) { $chunk_properties += array('chunkedHash' => $chunked_hash); } $chunk_engine = head($chunk_engines); $file = $chunk_engine->allocateChunks($length, $chunk_properties); return array('upload' => true, 'filePHID' => $file->getPHID()); } // None of the storage engines can accept this file. if (PhabricatorFileStorageEngine::loadWritableEngines()) { $error = pht('Unable to upload file: this file is too large for any ' . 'configured storage engine.'); } else { $error = pht('Unable to upload file: the server is not configured with any ' . 'writable storage engines.'); } return array('upload' => false, 'filePHID' => null, 'error' => $error); }
public function buildConfigurationPagePanel() { $viewer = $this->getViewer(); $application = $this->getApplication(); $engines = PhabricatorFileStorageEngine::loadAllEngines(); $writable_engines = PhabricatorFileStorageEngine::loadWritableEngines(); $chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines(); $yes = pht('Yes'); $no = pht('No'); $rows = array(); $rowc = array(); foreach ($engines as $key => $engine) { $limited = $no; $limit = null; if ($engine->hasFilesizeLimit()) { $limited = $yes; $limit = phutil_format_bytes($engine->getFilesizeLimit()); } if ($engine->canWriteFiles()) { $writable = $yes; } else { $writable = $no; } if ($engine->isTestEngine()) { $test = $yes; } else { $test = $no; } if (isset($writable_engines[$key]) || isset($chunk_engines[$key])) { $rowc[] = 'highlighted'; } else { $rowc[] = null; } $rows[] = array($key, get_class($engine), $test, $writable, $limited, $limit); } $table = id(new AphrontTableView($rows))->setNoDataString(pht('No storage engines available.'))->setHeaders(array(pht('Key'), pht('Class'), pht('Unit Test'), pht('Writable'), pht('Has Limit'), pht('Limit')))->setRowClasses($rowc)->setColumnClasses(array('', 'wide', '', '', '', 'n')); $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Storage Engines'))->setTable($table); return $box; }