1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-15 19:32:40 +01:00
phorge-phorge/src/applications/files/conduit/FileConduitAPIMethod.php
epriestley aa4adf3ab8 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
2015-03-13 11:30:24 -07:00

120 lines
2.7 KiB
PHP

<?php
abstract class FileConduitAPIMethod extends ConduitAPIMethod {
final public function getApplication() {
return PhabricatorApplication::getByClass('PhabricatorFilesApplication');
}
protected function loadFileByPHID(PhabricatorUser $viewer, $file_phid) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
if (!$file) {
throw new Exception(pht('No such file "%s"!', $file_phid));
}
return $file;
}
protected function loadFileChunks(
PhabricatorUser $viewer,
PhabricatorFile $file) {
return $this->newChunkQuery($viewer, $file)
->execute();
}
protected function loadFileChunkForUpload(
PhabricatorUser $viewer,
PhabricatorFile $file,
$start,
$end) {
$start = (int)$start;
$end = (int)$end;
$chunks = $this->newChunkQuery($viewer, $file)
->withByteRange($start, $end)
->execute();
if (!$chunks) {
throw new Exception(
pht(
'There are no file data chunks in byte range %d - %d.',
$start,
$end));
}
if (count($chunks) !== 1) {
phlog($chunks);
throw new Exception(
pht(
'There are multiple chunks in byte range %d - %d.',
$start,
$end));
}
$chunk = head($chunks);
if ($chunk->getByteStart() != $start) {
throw new Exception(
pht(
'Chunk start byte is %d, not %d.',
$chunk->getByteStart(),
$start));
}
if ($chunk->getByteEnd() != $end) {
throw new Exception(
pht(
'Chunk end byte is %d, not %d.',
$chunk->getByteEnd(),
$end));
}
if ($chunk->getDataFilePHID()) {
throw new Exception(
pht(
'Chunk has already been uploaded.'));
}
return $chunk;
}
protected function decodeBase64($data) {
$data = base64_decode($data, $strict = true);
if ($data === false) {
throw new Exception(pht('Unable to decode base64 data!'));
}
return $data;
}
protected function loadAnyMissingChunk(
PhabricatorUser $viewer,
PhabricatorFile $file) {
return $this->newChunkQuery($viewer, $file)
->withIsComplete(false)
->setLimit(1)
->execute();
}
private function newChunkQuery(
PhabricatorUser $viewer,
PhabricatorFile $file) {
$engine = $file->instantiateStorageEngine();
if (!$engine->isChunkEngine()) {
throw new Exception(
pht(
'File "%s" does not have chunks!',
$file->getPHID()));
}
return id(new PhabricatorFileChunkQuery())
->setViewer($viewer)
->withChunkHandles(array($file->getStorageHandle()));
}
}