Add support for partially uploaded files
Summary: Ref T7149. This flags allocated but incomplete files and doesn't explode when trying to download them. Files are marked complete when the last chunk is uploaded. I added a key on `<authorPHID, isPartial>` so we can show you a list of partially uploaded files and prompt you to resume them at some point down the road. Test Plan: Massaged debugging settings and uploaded README.md very slowly in 32b chunks. Saw the file lose its "Partial" flag when the last chunk finished. Reviewers: btrahan Reviewed By: btrahan Subscribers: joshuaspence, epriestley Maniphest Tasks: T7149 Differential Revision: https://secure.phabricator.com/D12063
This commit is contained in:
@@ -5,6 +5,7 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||
private $phid;
|
||||
private $key;
|
||||
private $token;
|
||||
private $file;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->phid = $data['phid'];
|
||||
@@ -16,20 +17,9 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function checkFileAndToken($file) {
|
||||
if (!$file) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if (!$file->validateSecretKey($this->key)) {
|
||||
return new Aphront403Response();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$alt = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
|
||||
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
||||
@@ -44,32 +34,22 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||
// Alternate files domain isn't configured or it's set
|
||||
// to the same as the default domain
|
||||
|
||||
// load the file with permissions checks;
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer($request->getUser())
|
||||
->withPHIDs(array($this->phid))
|
||||
->executeOne();
|
||||
|
||||
$error_response = $this->checkFileAndToken($file);
|
||||
if ($error_response) {
|
||||
return $error_response;
|
||||
$response = $this->loadFile($viewer);
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
$file = $this->getFile();
|
||||
|
||||
// when the file is not CDNable, don't allow cache
|
||||
$cache_response = $file->getCanCDN();
|
||||
} else if ($req_domain != $alt_domain) {
|
||||
// Alternate domain is configured but this request isn't using it
|
||||
|
||||
// load the file with permissions checks;
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer($request->getUser())
|
||||
->withPHIDs(array($this->phid))
|
||||
->executeOne();
|
||||
|
||||
$error_response = $this->checkFileAndToken($file);
|
||||
if ($error_response) {
|
||||
return $error_response;
|
||||
$response = $this->loadFile($viewer);
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
$file = $this->getFile();
|
||||
|
||||
// if the user can see the file, generate a token;
|
||||
// redirect to the alt domain with the token;
|
||||
@@ -82,18 +62,15 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||
->setURI($token_uri);
|
||||
|
||||
} else {
|
||||
// We are using the alternate domain
|
||||
// We are using the alternate domain. We don't have authentication
|
||||
// on this domain, so we bypass policy checks when loading the file.
|
||||
|
||||
// load the file, bypassing permission checks;
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs(array($this->phid))
|
||||
->executeOne();
|
||||
|
||||
$error_response = $this->checkFileAndToken($file);
|
||||
if ($error_response) {
|
||||
return $error_response;
|
||||
$bypass_policies = PhabricatorUser::getOmnipotentUser();
|
||||
$response = $this->loadFile($bypass_policies);
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
$file = $this->getFile();
|
||||
|
||||
$acquire_token_uri = id(new PhutilURI($file->getViewURI()))
|
||||
->setDomain($main_domain);
|
||||
@@ -205,4 +182,44 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
private function loadFile(PhabricatorUser $viewer) {
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($this->phid))
|
||||
->executeOne();
|
||||
|
||||
if (!$file) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if (!$file->validateSecretKey($this->key)) {
|
||||
return new Aphront403Response();
|
||||
}
|
||||
|
||||
if ($file->getIsPartial()) {
|
||||
// We may be on the CDN domain, so we need to use a fully-qualified URI
|
||||
// here to make sure we end up back on the main domain.
|
||||
$info_uri = PhabricatorEnv::getURI($file->getInfoURI());
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Partial Upload'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'This file has only been partially uploaded. It must be '.
|
||||
'uploaded completely before you can download it.'))
|
||||
->addCancelButton($info_uri);
|
||||
}
|
||||
|
||||
$this->file = $file;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getFile() {
|
||||
if (!$this->file) {
|
||||
throw new Exception(pht('Call loadFile() before getFile()!'));
|
||||
}
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user