Skip to content

Commit

Permalink
feat(api): File conversion API
Browse files Browse the repository at this point in the history
Signed-off-by: Elizabeth Danzberger <[email protected]>
  • Loading branch information
elzody committed Jan 7, 2025
1 parent 1ed3f03 commit e91c447
Show file tree
Hide file tree
Showing 21 changed files with 815 additions and 2 deletions.
1 change: 1 addition & 0 deletions apps/testing/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
'OCA\\Testing\\Conversion\\ConversionProvider' => $baseDir . '/../lib/Conversion/ConversionProvider.php',
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => $baseDir . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
Expand Down
1 change: 1 addition & 0 deletions apps/testing/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ComposerStaticInitTesting
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
'OCA\\Testing\\Conversion\\ConversionProvider' => __DIR__ . '/..' . '/../lib/Conversion/ConversionProvider.php',
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
Expand Down
3 changes: 3 additions & 0 deletions apps/testing/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace OCA\Testing\AppInfo;

use OCA\Testing\AlternativeHomeUserBackend;
use OCA\Testing\Conversion\ConversionProvider;
use OCA\Testing\Listener\GetDeclarativeSettingsValueListener;
use OCA\Testing\Listener\RegisterDeclarativeSettingsListener;
use OCA\Testing\Listener\SetDeclarativeSettingsValueListener;
Expand Down Expand Up @@ -49,6 +50,8 @@ public function register(IRegistrationContext $context): void {
$context->registerTaskProcessingProvider(FakeTranscribeProvider::class);
$context->registerTaskProcessingProvider(FakeContextWriteProvider::class);

$context->registerConversionProvider(ConversionProvider::class);

$context->registerDeclarativeSettings(DeclarativeSettingsForm::class);
$context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, RegisterDeclarativeSettingsListener::class);
$context->registerEventListener(DeclarativeSettingsGetValueEvent::class, GetDeclarativeSettingsValueListener::class);
Expand Down
39 changes: 39 additions & 0 deletions apps/testing/lib/Conversion/ConversionProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Testing\Conversion;

use OCP\Conversion\ConversionMimeTuple;
use OCP\Conversion\IConversionProvider;
use OCP\Files\File;

class ConversionProvider implements IConversionProvider {

public function getName(): string {
return 'testing';
}

public function getSupportedMimeTypes(): array {
$jpegConversions = new ConversionMimeTuple('image/jpeg', [
'image/png',
]);

return [$jpegConversions];
}

public function convertFile(File $file, string $targetMimeType): mixed {
$image = imagecreatefromstring($file->getContent());

imagepalettetotruecolor($image);

ob_start();
imagepng($image);
return ob_get_clean();
}
}
8 changes: 8 additions & 0 deletions config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,14 @@
*/
'metadata_max_filesize' => 256,

/**
* Maximum file size for file conversion.
* If a file exceeds this size, the file will not be converted.
*
* Default: 100 megabytes
*/
'max_conversion_filesize' => 100,

/**
* LDAP
*
Expand Down
76 changes: 76 additions & 0 deletions core/Controller/ConversionApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/


namespace OC\Core\Controller;

use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
use OCP\Conversion\IConversionManager;
use OCP\Files\File;
use OCP\Files\IRootFolder;
use OCP\IRequest;

class ConversionApiController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
private IConversionManager $conversionManager,
private IRootFolder $rootFolder,
private ?string $userId,
) {
parent::__construct($appName, $request);
}

/**
* Converts a file from one MIME type to another
*
* @param int $fileId ID of the file to be converted
* @param string $targetMimeType The MIME type to which you want to convert the file
* @param string|null $destination The target path of the converted file. Written to a temporary file if left empty
*
* @return DataResponse<Http::STATUS_CREATED, array{path: string}, array{}>
*
* 201: File was converted and written to the destination or temporary file
*
* @throws OCSException The file was unable to be converted
* @throws OCSNotFoundException The file to be converted was not found
*/
#[NoAdminRequired]
#[UserRateLimit(limit: 25, period: 120)]
#[ApiRoute(verb: 'POST', url: '/convert', root: '/conversion')]
public function convert(int $fileId, string $targetMimeType, ?string $destination = null): DataResponse {
$userFolder = $this->rootFolder->getUserFolder($this->userId);
$file = $userFolder->getFirstNodeById($fileId);

if (!($file instanceof File)) {
throw new OCSNotFoundException();
}

try {
if ($destination !== null) {
$destination = $userFolder->getFullpath($destination);
}

$convertedFile = $this->conversionManager->convert($file, $targetMimeType, $destination);
} catch (\Exception $e) {
throw new OCSException($e->getMessage());
}

return new DataResponse([
'path' => $convertedFile,
], Http::STATUS_CREATED);
}
}
7 changes: 7 additions & 0 deletions core/openapi-ex_app.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"webdav-root",
"reference-api",
"reference-regex",
"conversions",
"mod-rewrite-working"
],
"properties": {
Expand All @@ -49,6 +50,12 @@
"reference-regex": {
"type": "string"
},
"conversions": {
"type": "object",
"additionalProperties": {
"type": "object"
}
},
"mod-rewrite-working": {
"type": "boolean"
}
Expand Down
134 changes: 134 additions & 0 deletions core/openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"webdav-root",
"reference-api",
"reference-regex",
"conversions",
"mod-rewrite-working"
],
"properties": {
Expand All @@ -115,6 +116,12 @@
"reference-regex": {
"type": "string"
},
"conversions": {
"type": "object",
"additionalProperties": {
"type": "object"
}
},
"mod-rewrite-working": {
"type": "boolean"
}
Expand Down Expand Up @@ -2535,6 +2542,133 @@
}
}
},
"/ocs/v2.php/conversion/convert": {
"post": {
"operationId": "conversion_api-convert",
"summary": "Converts a file from one MIME type to another",
"tags": [
"conversion_api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"fileId",
"targetMimeType"
],
"properties": {
"fileId": {
"type": "integer",
"format": "int64",
"description": "ID of the file to be converted"
},
"targetMimeType": {
"type": "string",
"description": "The MIME type to which you want to convert the file"
},
"destination": {
"type": "string",
"nullable": true,
"description": "The target path of the converted file. Written to a temporary file if left empty"
}
}
}
}
}
},
"parameters": [
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"201": {
"description": "File was converted and written to the destination or temporary file",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
}
}
}
}
}
}
}
}
}
},
"404": {
"description": "The file to be converted was not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/hovercard/v1/{userId}": {
"get": {
"operationId": "hover_card-get-user",
Expand Down
Loading

0 comments on commit e91c447

Please sign in to comment.