Skip to content

Commit a21d58d

Browse files
committed
Feat(file): add support of the chunked file upload (improvements)
Signed-off-by: Kostiantyn Miakshyn <molodchick@gmail.com>
1 parent 1ef8536 commit a21d58d

3 files changed

Lines changed: 48 additions & 4 deletions

File tree

‎lib/BackgroundJob/CleanupUploadedFilesJob.php‎

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
use OCP\BackgroundJob\TimedJob;
1616
use OCP\Files\Folder;
1717
use OCP\Files\IRootFolder;
18+
use OCP\Files\NotFoundException;
1819
use OCP\Share\IManager;
1920
use OCP\Share\IShare;
21+
use OCP\User\Exceptions\UserNotFoundException;
2022
use Psr\Log\LoggerInterface;
2123

2224
class CleanupUploadedFilesJob extends TimedJob {
@@ -66,7 +68,15 @@ public function run($argument): void {
6668
}
6769

6870
$usersToCleanup[$form->getOwnerId()] = true;
69-
$userFolder = $this->rootFolder->getUserFolder($form->getOwnerId());
71+
try {
72+
$userFolder = $this->rootFolder->getUserFolder($form->getOwnerId());
73+
} catch (UserNotFoundException $e) {
74+
$this->logger->warning('Could not find user {ownerId} for uploaded file deletion.', [
75+
'ownerId' => $form->getOwnerId(),
76+
]);
77+
$this->uploadedFileMapper->delete($uploadedFile);
78+
continue;
79+
}
7080

7181
$nodes = $userFolder->getById($uploadedFile->getFileId());
7282

@@ -86,17 +96,28 @@ public function run($argument): void {
8696

8797
$this->logger->info('Deleted {deleted} uploaded files.', ['deleted' => $deleted]);
8898

99+
// Files uploaded to an upload share that were never registered leave no
100+
// database record behind, so every form owner needs to be checked.
101+
foreach ($this->formMapper->findAllOwnerIds() as $ownerId) {
102+
$usersToCleanup[$ownerId] = true;
103+
}
104+
89105
// now delete empty folders in user folders
90106
$deleted = 0;
91107
foreach (array_keys($usersToCleanup) as $userId) {
92-
$this->logger->info('Cleaning up empty folders for user {userId}.', ['userId' => $userId]);
93-
$userFolder = $this->rootFolder->getUserFolder($userId);
108+
try {
109+
$userFolder = $this->rootFolder->getUserFolder($userId);
110+
$unsubmittedFilesFolder = $userFolder->get(Constants::UNSUBMITTED_FILES_FOLDER);
111+
} catch (UserNotFoundException|NotFoundException $e) {
112+
continue;
113+
}
94114

95-
$unsubmittedFilesFolder = $userFolder->get(Constants::UNSUBMITTED_FILES_FOLDER);
96115
if (!$unsubmittedFilesFolder instanceof Folder) {
97116
continue;
98117
}
99118

119+
$this->logger->info('Cleaning up empty folders for user {userId}.', ['userId' => $userId]);
120+
100121
foreach ($unsubmittedFilesFolder->getDirectoryListing() as $node) {
101122
if ($node->getName() < $dateTime->getTimestamp()) {
102123
if ($node instanceof Folder) {

‎lib/Controller/ApiController.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,10 @@ public function createUploadShare(int $formId, int $questionId, string $shareHas
17941794
$share->setSharedBy($form->getOwnerId());
17951795
$share->setShareOwner($form->getOwnerId());
17961796
$share->setLabel($this->l10n->t('Forms file upload'));
1797+
// Temporary shares are cleaned up together with the upload folder after
1798+
// an hour; the expiration is only a safety net if cleanup never runs.
1799+
// Share expiration is day-granular, so one day is the shortest value.
1800+
$share->setExpirationDate(new \DateTime('+1 day'));
17971801

17981802
try {
17991803
$share = $this->shareManager->createShare($share);

‎lib/Db/FormMapper.php‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,25 @@ public function findByHash(string $hash): Form {
105105
return $this->findEntity($qb);
106106
}
107107

108+
/**
109+
* @return list<string> IDs of all users that own at least one form
110+
*/
111+
public function findAllOwnerIds(): array {
112+
$qb = $this->db->getQueryBuilder();
113+
114+
$qb->selectDistinct('owner_id')
115+
->from($this->getTableName());
116+
117+
$result = $qb->executeQuery();
118+
$ownerIds = array_map(
119+
static fn (array $row): string => (string)$row['owner_id'],
120+
$result->fetchAll(),
121+
);
122+
$result->closeCursor();
123+
124+
return $ownerIds;
125+
}
126+
108127
/**
109128
* Get forms shared with the user
110129
* @param string $userId The user ID

0 commit comments

Comments
 (0)