whereTeamId(0)->where('is_usable', true)->find($this->s3StorageId); if (! $storage) { throw new \RuntimeException('The file download storage is not available.'); } $server = Server::findOrFail($this->serverId); $key = FileDownloadStorageService::newObjectKey(); // Queue the delete first, so a partial upload is removed as well. DeleteFileDownloadJob::dispatch($storage->id, $key)->delay(now()->addHours(FileDownloadStorageService::OBJECT_TTL_HOURS)); $upload = $downloads->uploadUrl($storage, $key, $this->downloadName); if ($this->container === null) { instant_remote_process([FileDownloadStorageService::buildHostFileUploadCommand($this->path, $upload['url'], $upload['headers'])], $server, timeout: 3600); } else { (new ContainerFilesystemService($server, $this->container))->uploadToS3($this->path, $this->isDir, $upload['url'], $upload['headers']); } $this->store(['status' => 'ready', 'url' => $downloads->downloadUrl($storage, $key)]); } catch (\Throwable $e) { // The message can contain the S3 endpoint or a presigned URL; keep it in the log only. Log::warning('S3 download failed', ['download_id' => $this->downloadId, 'error' => $e->getMessage()]); $this->store(['status' => 'failed', 'message' => 'Download failed. The file could not be uploaded to the download storage. Try again, or ask your administrator to check the storage settings.']); } } /** * @param array $result */ private function store(array $result): void { Cache::put(self::cacheKey($this->downloadId), ['user_id' => $this->userId, ...$result], now()->addMinutes(FileDownloadStorageService::LINK_TTL_MINUTES)); } }