Support HTML5 / Javascript chunked file uploads
Summary: Ref T7149. This adds chunking support to drag-and-drop uploads. It never activates right now unless you hack things up, since the chunk engine is still hard-coded as disabled. The overall approach is the same as `arc upload` in D12061, with some slight changes to the API return values to avoid a few extra HTTP calls. Test Plan: - Enabled chunk engine. - Uploaded some READMEs in a bunch of tiny 32 byte chunks. - Worked out of the box in Safari, Chrome, Firefox. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7149 Differential Revision: https://secure.phabricator.com/D12066
This commit is contained in:
@@ -13,18 +13,82 @@ final class PhabricatorFileDropUploadController
|
||||
// NOTE: Throws if valid CSRF token is not present in the request.
|
||||
$request->validateCSRF();
|
||||
|
||||
$data = PhabricatorStartup::getRawInput();
|
||||
$name = $request->getStr('name');
|
||||
|
||||
$file_phid = $request->getStr('phid');
|
||||
// If there's no explicit view policy, make it very restrictive by default.
|
||||
// This is the correct policy for files dropped onto objects during
|
||||
// creation, comment and edit flows.
|
||||
|
||||
$view_policy = $request->getStr('viewPolicy');
|
||||
if (!$view_policy) {
|
||||
$view_policy = $viewer->getPHID();
|
||||
}
|
||||
|
||||
$is_chunks = $request->getBool('querychunks');
|
||||
if ($is_chunks) {
|
||||
$params = array(
|
||||
'filePHID' => $file_phid,
|
||||
);
|
||||
|
||||
$result = id(new ConduitCall('file.querychunks', $params))
|
||||
->setUser($viewer)
|
||||
->execute();
|
||||
|
||||
return id(new AphrontAjaxResponse())->setContent($result);
|
||||
}
|
||||
|
||||
$is_allocate = $request->getBool('allocate');
|
||||
if ($is_allocate) {
|
||||
$params = array(
|
||||
'name' => $name,
|
||||
'contentLength' => $request->getInt('length'),
|
||||
'viewPolicy' => $view_policy,
|
||||
|
||||
// TODO: Remove.
|
||||
// 'forceChunking' => true,
|
||||
);
|
||||
|
||||
$result = id(new ConduitCall('file.allocate', $params))
|
||||
->setUser($viewer)
|
||||
->execute();
|
||||
|
||||
$file_phid = $result['filePHID'];
|
||||
if ($file_phid) {
|
||||
$file = $this->loadFile($file_phid);
|
||||
$result += $this->getFileDictionary($file);
|
||||
}
|
||||
|
||||
return id(new AphrontAjaxResponse())->setContent($result);
|
||||
}
|
||||
|
||||
// Read the raw request data. We're either doing a chunk upload or a
|
||||
// vanilla upload, so we need it.
|
||||
$data = PhabricatorStartup::getRawInput();
|
||||
|
||||
|
||||
$is_chunk_upload = $request->getBool('uploadchunk');
|
||||
if ($is_chunk_upload) {
|
||||
$params = array(
|
||||
'filePHID' => $file_phid,
|
||||
'byteStart' => $request->getInt('byteStart'),
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
$result = id(new ConduitCall('file.uploadchunk', $params))
|
||||
->setUser($viewer)
|
||||
->execute();
|
||||
|
||||
$file = $this->loadFile($file_phid);
|
||||
if ($file->getIsPartial()) {
|
||||
$result = array();
|
||||
} else {
|
||||
$result = array(
|
||||
'complete' => true,
|
||||
) + $this->getFileDictionary($file);
|
||||
}
|
||||
|
||||
return id(new AphrontAjaxResponse())->setContent($result);
|
||||
}
|
||||
|
||||
$file = PhabricatorFile::newFromXHRUpload(
|
||||
$data,
|
||||
array(
|
||||
@@ -34,12 +98,30 @@ final class PhabricatorFileDropUploadController
|
||||
'isExplicitUpload' => true,
|
||||
));
|
||||
|
||||
return id(new AphrontAjaxResponse())->setContent(
|
||||
array(
|
||||
'id' => $file->getID(),
|
||||
'phid' => $file->getPHID(),
|
||||
'uri' => $file->getBestURI(),
|
||||
));
|
||||
$result = $this->getFileDictionary($file);
|
||||
return id(new AphrontAjaxResponse())->setContent($result);
|
||||
}
|
||||
|
||||
private function getFileDictionary(PhabricatorFile $file) {
|
||||
return array(
|
||||
'id' => $file->getID(),
|
||||
'phid' => $file->getPHID(),
|
||||
'uri' => $file->getBestURI(),
|
||||
);
|
||||
}
|
||||
|
||||
private function loadFile($file_phid) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($file_phid))
|
||||
->executeOne();
|
||||
if (!$file) {
|
||||
throw new Exception(pht('Failed to load file.'));
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user