getQueryParams()['content'] ?? ''; if ($content === '') { throw new \InvalidArgumentException('Content of the QR Code cannot be empty', 1762811499); } $size = QrCodeSize::tryFrom((string)($request->getQueryParams()['size'] ?? '')) ?? QrCodeSize::MEDIUM; $svg = $this->getQrCodeSvg($content, $size); $response = $this->responseFactory->createResponse(); return $response ->withHeader('Content-Type', 'image/svg+xml') ->withBody($this->streamFactory->createStream($svg)); } public function downloadAction(ServerRequestInterface $request): ResponseInterface { $body = $request->getParsedBody(); $content = (string)($body['content'] ?? ''); if ($content === '') { throw new \InvalidArgumentException('Content of the QR Code cannot be empty', 1762811481); } $size = QrCodeSize::tryFrom((string)($body['size'] ?? '')) ?? QrCodeSize::SMALL; $format = (string)($body['format'] ?? 'svg'); $svgContent = $this->getQrCodeSvg($content, $size); $path = Environment::getVarPath() . '/transient/'; GeneralUtility::mkdir_deep($path); $fileName = $path . 'qrcode-' . $size->getSize() . 'px-' . sha1($svgContent); $svgFilePath = $fileName . '.svg'; if ($format === 'png') { $pixelGraphicFilePath = $fileName . '.png'; $this->createSvg($svgFilePath, $svgContent); $filePath = $this->convertTo($svgFilePath, $pixelGraphicFilePath, 'png', $size); } elseif ($format === 'svg') { $filePath = $this->createSvg($svgFilePath, $svgContent); } else { throw new \InvalidArgumentException('The suffix "' . $format . '" is not supported.', 1762718268); } return $this->sendFile($filePath, $format); } /** * Send file to the browser to download */ private function sendFile(string $filePath, string $format = 'svg'): ResponseInterface { $mimeType = $this->mimeTypeDetector->getMimeTypesForFileExtension($format); $response = $this->responseFactory->createResponse(); $fileContent = file_get_contents($filePath); $response->getBody()->write($fileContent); return $response ->withHeader('Content-Type', $mimeType[0] ?? 'image/svg+xml') ->withHeader('Content-Disposition', 'attachment; filename="' . basename($filePath) . '"') ->withHeader('Content-Length', (string)strlen($fileContent)); } private function getQrCodeSvg(string $content, QrCodeSize $size = QrCodeSize::MEDIUM): string { $qrCodeRenderer = new ImageRenderer(new RendererStyle($size->getSize(), 2), new SvgImageBackEnd()); return (new Writer($qrCodeRenderer))->writeString($content); } private function createSvg(string $file, string $content): string { if (file_exists($file)) { return $file; } if (!GeneralUtility::writeFile($file, $content, true)) { throw new \RuntimeException('Unable to write file ' . $file, 1762718307); } return $file; } /** * Create a pixel based image file from a given SVG file */ private function convertTo(string $sourcePath, string $targetPath, string $format, QrCodeSize $size = QrCodeSize::SMALL): string { if (file_exists($targetPath)) { return $targetPath; } $result = $this->graphicalFunctions->resize( $sourcePath, $format, (string)$size->getSize(), (string)$size->getSize(), '', [], true ); if ($result) { $pngFile = $result->getRealPath(); if ($pngFile && is_file($pngFile) && rename($pngFile, $targetPath)) { return $targetPath; } } throw new \RuntimeException('Failed create ' . strtoupper($format) . ' ' . $targetPath . ' from SVG ' . $sourcePath . ' file.', 1762718351); } }