@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<?php
2
3final class FileUploadChunkConduitAPIMethod
4 extends FileConduitAPIMethod {
5
6 public function getAPIMethodName() {
7 return 'file.uploadchunk';
8 }
9
10 public function getMethodDescription() {
11 return pht('Upload a chunk of file data to the server.');
12 }
13
14 protected function defineParamTypes() {
15 return array(
16 'filePHID' => 'phid',
17 'byteStart' => 'int',
18 'data' => 'string',
19 'dataEncoding' => 'string',
20 );
21 }
22
23 protected function defineReturnType() {
24 return 'void';
25 }
26
27 protected function defineErrorTypes() {
28 return array(
29 'ERR-BAD-PHID' => pht('Must pass a PHID.'),
30 );
31 }
32
33 protected function execute(ConduitAPIRequest $request) {
34 $viewer = $request->getUser();
35
36 $file_phid = $request->getValue('filePHID');
37 if (!$file_phid) {
38 throw new ConduitException('ERR-BAD-PHID');
39 }
40 $file = $this->loadFileByPHID($viewer, $file_phid);
41
42 $start = $request->getValue('byteStart');
43
44 $data = $request->getValue('data');
45 $encoding = $request->getValue('dataEncoding');
46 switch ($encoding) {
47 case 'base64':
48 $data = $this->decodeBase64($data);
49 break;
50 case null:
51 break;
52 default:
53 throw new Exception(pht('Unsupported data encoding.'));
54 }
55 $length = strlen($data);
56
57 $chunk = $this->loadFileChunkForUpload(
58 $viewer,
59 $file,
60 $start,
61 $start + $length);
62
63 // If this is the initial chunk, leave the MIME type unset so we detect
64 // it and can update the parent file. If this is any other chunk, it has
65 // no meaningful MIME type. Provide a default type so we can avoid writing
66 // it to disk to perform MIME type detection.
67 if (!$start) {
68 $mime_type = null;
69 } else {
70 $mime_type = 'application/octet-stream';
71 }
72
73 $params = array(
74 'name' => $file->getMonogram().'.chunk-'.$chunk->getID(),
75 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
76 'chunk' => true,
77 );
78
79 if ($mime_type !== null) {
80 $params['mime-type'] = 'application/octet-stream';
81 }
82
83 // NOTE: These files have a view policy which prevents normal access. They
84 // are only accessed through the storage engine.
85 $chunk_data = PhabricatorFile::newFromFileData(
86 $data,
87 $params);
88
89 $chunk->setDataFilePHID($chunk_data->getPHID())->save();
90
91 $needs_update = false;
92
93 $missing = $this->loadAnyMissingChunk($viewer, $file);
94 if (!$missing) {
95 $file->setIsPartial(0);
96 $needs_update = true;
97 }
98
99 if (!$start) {
100 $file->setMimeType($chunk_data->getMimeType());
101 $needs_update = true;
102 }
103
104 if ($needs_update) {
105 $file->save();
106 }
107
108 return null;
109 }
110
111}