@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Enable the chunk storage engine

Summary: Ref T7149. This works now, so enable it.

Test Plan:
- Uploaded large and small files in Firefox, Safari and Chrome.
- Uploaded large files with `arc upload`.
- Stopped/resumed large files with all clients.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7149

Differential Revision: https://secure.phabricator.com/D12079

+40 -56
+11 -11
resources/celerity/map.php
··· 11 11 'core.pkg.js' => '69f7e542', 12 12 'darkconsole.pkg.js' => '8ab24e01', 13 13 'differential.pkg.css' => '1940be3f', 14 - 'differential.pkg.js' => 'be1e5f9b', 14 + 'differential.pkg.js' => '85fd84c6', 15 15 'diffusion.pkg.css' => '591664fa', 16 16 'diffusion.pkg.js' => 'bfc0737b', 17 17 'maniphest.pkg.css' => '68d4dd3d', ··· 437 437 'rsrc/js/application/uiexample/gesture-example.js' => '558829c2', 438 438 'rsrc/js/application/uiexample/notification-example.js' => '8ce821c5', 439 439 'rsrc/js/core/Busy.js' => '6453c869', 440 - 'rsrc/js/core/DragAndDropFileUpload.js' => 'fd6ace61', 440 + 'rsrc/js/core/DragAndDropFileUpload.js' => '7fa4b248', 441 441 'rsrc/js/core/DraggableList.js' => 'a16ec1c6', 442 442 'rsrc/js/core/FileUpload.js' => '477359c8', 443 443 'rsrc/js/core/Hovercard.js' => '7e8468ae', ··· 717 717 'phabricator-core-css' => '86bfbe8c', 718 718 'phabricator-countdown-css' => '86b7b0a0', 719 719 'phabricator-dashboard-css' => '17937d22', 720 - 'phabricator-drag-and-drop-file-upload' => 'fd6ace61', 720 + 'phabricator-drag-and-drop-file-upload' => '7fa4b248', 721 721 'phabricator-draggable-list' => 'a16ec1c6', 722 722 'phabricator-fatal-config-template-css' => '8e6c6fcd', 723 723 'phabricator-feed-css' => 'b513b5f4', ··· 1423 1423 'javelin-behavior', 1424 1424 'javelin-history', 1425 1425 ), 1426 + '7fa4b248' => array( 1427 + 'javelin-install', 1428 + 'javelin-util', 1429 + 'javelin-request', 1430 + 'javelin-dom', 1431 + 'javelin-uri', 1432 + 'phabricator-file-upload', 1433 + ), 1426 1434 82439934 => array( 1427 1435 'javelin-behavior', 1428 1436 'javelin-dom', ··· 1991 1999 'javelin-behavior', 1992 2000 'javelin-dom', 1993 2001 'phortune-credit-card-form', 1994 - ), 1995 - 'fd6ace61' => array( 1996 - 'javelin-install', 1997 - 'javelin-util', 1998 - 'javelin-request', 1999 - 'javelin-dom', 2000 - 'javelin-uri', 2001 - 'phabricator-file-upload', 2002 2002 ), 2003 2003 'fe287620' => array( 2004 2004 'javelin-install',
-1
src/applications/files/controller/PhabricatorFileDropUploadController.php
··· 61 61 // vanilla upload, so we need it. 62 62 $data = PhabricatorStartup::getRawInput(); 63 63 64 - 65 64 $is_chunk_upload = $request->getBool('uploadchunk'); 66 65 if ($is_chunk_upload) { 67 66 $params = array(
+7 -10
src/applications/files/engine/PhabricatorChunkedFileStorageEngine.php
··· 14 14 /** 15 15 * We can write chunks if we have at least one valid storage engine 16 16 * underneath us. 17 - * 18 - * This engine must not also be a chunk engine. 19 17 */ 20 18 public function canWriteFiles() { 21 19 return (bool)$this->getWritableEngine(); ··· 26 24 } 27 25 28 26 public function isChunkEngine() { 29 - return true; 30 - } 31 - 32 - public function isTestEngine() { 33 - // TODO: For now, prevent this from actually being selected. 34 27 return true; 35 28 } 36 29 ··· 142 135 return $file; 143 136 } 144 137 138 + /** 139 + * Find a storage engine which is suitable for storing chunks. 140 + * 141 + * This engine must be a writable engine, have a filesize limit larger than 142 + * the chunk limit, and must not be a chunk engine itself. 143 + */ 145 144 private function getWritableEngine() { 146 145 // NOTE: We can't just load writable engines or we'll loop forever. 147 146 $engines = PhabricatorFileStorageEngine::loadAllEngines(); ··· 172 171 } 173 172 174 173 public function getChunkSize() { 175 - // TODO: This is an artificially small size to make it easier to 176 - // test chunking. 177 - return 32; 174 + return (4 * 1024 * 1024); 178 175 } 179 176 180 177 public function getFileDataIterator(PhabricatorFile $file, $begin, $end) {
+12 -2
src/applications/files/engine/PhabricatorFileStorageEngine.php
··· 82 82 * @return bool `true` if the engine has a filesize limit. 83 83 * @task meta 84 84 */ 85 - abstract public function hasFilesizeLimit(); 85 + public function hasFilesizeLimit() { 86 + return true; 87 + } 86 88 87 89 88 90 /** ··· 92 94 * an engine has a limit. Engines without a limit can store files of any 93 95 * size. 94 96 * 97 + * By default, engines define a limit which supports chunked storage of 98 + * large files. In most cases, you should not change this limit, even if an 99 + * engine has vast storage capacity: chunked storage makes large files more 100 + * manageable and enables features like resumable uploads. 101 + * 95 102 * @return int Maximum storable file size, in bytes. 96 103 * @task meta 97 104 */ 98 105 public function getFilesizeLimit() { 99 - throw new PhutilMethodNotImplementedException(); 106 + // NOTE: This 8MB limit is selected to be larger than the 4MB chunk size, 107 + // but not much larger. Files between 0MB and 8MB will be stored normally; 108 + // files larger than 8MB will be chunked. 109 + return (1024 * 1024 * 8); 100 110 } 101 111 102 112
-5
src/applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php
··· 30 30 } 31 31 32 32 33 - public function hasFilesizeLimit() { 34 - return false; 35 - } 36 - 37 - 38 33 /* -( Managing File Data )------------------------------------------------- */ 39 34 40 35
-5
src/applications/files/engine/PhabricatorS3FileStorageEngine.php
··· 33 33 } 34 34 35 35 36 - public function hasFilesizeLimit() { 37 - return false; 38 - } 39 - 40 - 41 36 /* -( Managing File Data )------------------------------------------------- */ 42 37 43 38
+4
src/applications/files/query/PhabricatorFileSearchEngine.php
··· 176 176 $item->addIcon('blame', pht('Temporary')); 177 177 } 178 178 179 + if ($file->getIsPartial()) { 180 + $item->addIcon('fa-exclamation-triangle orange', pht('Partial')); 181 + } 182 + 179 183 if (isset($highlighted_ids[$id])) { 180 184 $item->setEffect('highlighted'); 181 185 }
+6 -22
webroot/rsrc/js/core/DragAndDropFileUpload.js
··· 264 264 for (var ii = 0; ii < chunks.length; ii++) { 265 265 chunk = chunks[ii]; 266 266 if (!chunk.complete) { 267 - this._readChunk( 268 - file, 269 - chunk, 270 - JX.bind(this, this._didReadChunk, file, chunk)); 267 + this._uploadChunk(file, chunk); 271 268 break; 272 269 } 273 270 } 274 271 }, 275 272 276 - _readChunk: function(file, chunk, callback) { 277 - var reader = new FileReader(); 278 - var blob = file.getRawFileObject().slice(chunk.byteStart, chunk.byteEnd); 279 - 280 - reader.onload = function() { 281 - callback(reader.result); 282 - }; 283 - 284 - reader.onerror = function() { 285 - this._failUpload(file, {error: reader.error.message}); 286 - }; 287 - 288 - reader.readAsBinaryString(blob); 289 - }, 290 - 291 - _didReadChunk: function(file, chunk, data) { 273 + _uploadChunk: function(file, chunk, callback) { 292 274 file 293 275 .setStatus('upload') 294 276 .update(); ··· 316 298 req.listen('error', JX.bind(this, this._onUploadError, req, file)); 317 299 req.listen('uploadprogress', onprogress); 318 300 301 + var blob = file.getRawFileObject().slice(chunk.byteStart, chunk.byteEnd); 302 + 319 303 req 320 - .setRawData(data) 304 + .setRawData(blob) 321 305 .send(); 322 306 }, 323 307 ··· 390 374 this.invoke('didError', file); 391 375 }, 392 376 393 - _onUploadError: function(file, req, error) { 377 + _onUploadError: function(req, file, error) { 394 378 file.setStatus('error'); 395 379 396 380 if (error) {