mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-28 01:32:42 +01:00
e1d6bad864
Summary: Depends on D18828. Ref T7789. See <https://discourse.phabricator-community.org/t/git-lfs-fails-with-large-images/584>. Currently, when you upload a large (>4MB) image, we may try to assess the dimensions for the image and for each individual chunk. At best, this is slow and not useful. At worst, it fatals or consumes a ton of memory and I/O we don't need to be using. Instead: - Don't try to assess dimensions for chunked files. - Don't try to assess dimensions for the chunks themselves. - Squelch errors for bad data, etc., that `gd` can't actually read, since we recover sensibly. Test Plan: - Created a 2048x2048 PNG in Photoshop using the "Random Noise" filter which weighs 8.5MB. - Uploaded it. - Before patch: got complaints in log about `imagecreatefromstring()` failing, although the actual upload went OK in my environment. - After patch: clean log, no attempt to detect the size of a big image. - Also uploaded a small image, got dimensions detected properly still. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T7789 Differential Revision: https://secure.phabricator.com/D18830
102 lines
2.5 KiB
PHP
102 lines
2.5 KiB
PHP
<?php
|
|
|
|
final class FileUploadChunkConduitAPIMethod
|
|
extends FileConduitAPIMethod {
|
|
|
|
public function getAPIMethodName() {
|
|
return 'file.uploadchunk';
|
|
}
|
|
|
|
public function getMethodDescription() {
|
|
return pht('Upload a chunk of file data to the server.');
|
|
}
|
|
|
|
protected function defineParamTypes() {
|
|
return array(
|
|
'filePHID' => 'phid',
|
|
'byteStart' => 'int',
|
|
'data' => 'string',
|
|
'dataEncoding' => 'string',
|
|
);
|
|
}
|
|
|
|
protected function defineReturnType() {
|
|
return 'void';
|
|
}
|
|
|
|
protected function execute(ConduitAPIRequest $request) {
|
|
$viewer = $request->getUser();
|
|
|
|
$file_phid = $request->getValue('filePHID');
|
|
$file = $this->loadFileByPHID($viewer, $file_phid);
|
|
|
|
$start = $request->getValue('byteStart');
|
|
|
|
$data = $request->getValue('data');
|
|
$encoding = $request->getValue('dataEncoding');
|
|
switch ($encoding) {
|
|
case 'base64':
|
|
$data = $this->decodeBase64($data);
|
|
break;
|
|
case null:
|
|
break;
|
|
default:
|
|
throw new Exception(pht('Unsupported data encoding.'));
|
|
}
|
|
$length = strlen($data);
|
|
|
|
$chunk = $this->loadFileChunkForUpload(
|
|
$viewer,
|
|
$file,
|
|
$start,
|
|
$start + $length);
|
|
|
|
// If this is the initial chunk, leave the MIME type unset so we detect
|
|
// it and can update the parent file. If this is any other chunk, it has
|
|
// no meaningful MIME type. Provide a default type so we can avoid writing
|
|
// it to disk to perform MIME type detection.
|
|
if (!$start) {
|
|
$mime_type = null;
|
|
} else {
|
|
$mime_type = 'application/octet-stream';
|
|
}
|
|
|
|
$params = array(
|
|
'name' => $file->getMonogram().'.chunk-'.$chunk->getID(),
|
|
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
|
|
'chunk' => true,
|
|
);
|
|
|
|
if ($mime_type !== null) {
|
|
$params['mime-type'] = 'application/octet-stream';
|
|
}
|
|
|
|
// NOTE: These files have a view policy which prevents normal access. They
|
|
// are only accessed through the storage engine.
|
|
$chunk_data = PhabricatorFile::newFromFileData(
|
|
$data,
|
|
$params);
|
|
|
|
$chunk->setDataFilePHID($chunk_data->getPHID())->save();
|
|
|
|
$needs_update = false;
|
|
|
|
$missing = $this->loadAnyMissingChunk($viewer, $file);
|
|
if (!$missing) {
|
|
$file->setIsPartial(0);
|
|
$needs_update = true;
|
|
}
|
|
|
|
if (!$start) {
|
|
$file->setMimeType($chunk_data->getMimeType());
|
|
$needs_update = true;
|
|
}
|
|
|
|
if ($needs_update) {
|
|
$file->save();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
}
|