Skip to content

Commit e91c447

Browse files
committed
feat(api): File conversion API
Signed-off-by: Elizabeth Danzberger <lizzy7128@tutanota.de>
1 parent 1ed3f03 commit e91c447

File tree

21 files changed

+815
-2
lines changed

21 files changed

+815
-2
lines changed

apps/testing/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
1313
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
1414
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
15+
'OCA\\Testing\\Conversion\\ConversionProvider' => $baseDir . '/../lib/Conversion/ConversionProvider.php',
1516
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
1617
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => $baseDir . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
1718
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',

apps/testing/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ComposerStaticInitTesting
2727
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
2828
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
2929
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
30+
'OCA\\Testing\\Conversion\\ConversionProvider' => __DIR__ . '/..' . '/../lib/Conversion/ConversionProvider.php',
3031
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
3132
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
3233
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',

apps/testing/lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace OCA\Testing\AppInfo;
88

99
use OCA\Testing\AlternativeHomeUserBackend;
10+
use OCA\Testing\Conversion\ConversionProvider;
1011
use OCA\Testing\Listener\GetDeclarativeSettingsValueListener;
1112
use OCA\Testing\Listener\RegisterDeclarativeSettingsListener;
1213
use OCA\Testing\Listener\SetDeclarativeSettingsValueListener;
@@ -49,6 +50,8 @@ public function register(IRegistrationContext $context): void {
4950
$context->registerTaskProcessingProvider(FakeTranscribeProvider::class);
5051
$context->registerTaskProcessingProvider(FakeContextWriteProvider::class);
5152

53+
$context->registerConversionProvider(ConversionProvider::class);
54+
5255
$context->registerDeclarativeSettings(DeclarativeSettingsForm::class);
5356
$context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, RegisterDeclarativeSettingsListener::class);
5457
$context->registerEventListener(DeclarativeSettingsGetValueEvent::class, GetDeclarativeSettingsValueListener::class);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Testing\Conversion;
11+
12+
use OCP\Conversion\ConversionMimeTuple;
13+
use OCP\Conversion\IConversionProvider;
14+
use OCP\Files\File;
15+
16+
class ConversionProvider implements IConversionProvider {
17+
18+
public function getName(): string {
19+
return 'testing';
20+
}
21+
22+
public function getSupportedMimeTypes(): array {
23+
$jpegConversions = new ConversionMimeTuple('image/jpeg', [
24+
'image/png',
25+
]);
26+
27+
return [$jpegConversions];
28+
}
29+
30+
public function convertFile(File $file, string $targetMimeType): mixed {
31+
$image = imagecreatefromstring($file->getContent());
32+
33+
imagepalettetotruecolor($image);
34+
35+
ob_start();
36+
imagepng($image);
37+
return ob_get_clean();
38+
}
39+
}

config/config.sample.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,14 @@
14281428
*/
14291429
'metadata_max_filesize' => 256,
14301430

1431+
/**
1432+
* Maximum file size for file conversion.
1433+
* If a file exceeds this size, the file will not be converted.
1434+
*
1435+
* Default: 100 megabytes
1436+
*/
1437+
'max_conversion_filesize' => 100,
1438+
14311439
/**
14321440
* LDAP
14331441
*
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
11+
namespace OC\Core\Controller;
12+
13+
use OCP\AppFramework\Http;
14+
use OCP\AppFramework\Http\Attribute\ApiRoute;
15+
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
16+
use OCP\AppFramework\Http\Attribute\UserRateLimit;
17+
use OCP\AppFramework\Http\DataResponse;
18+
use OCP\AppFramework\OCS\OCSException;
19+
use OCP\AppFramework\OCS\OCSNotFoundException;
20+
use OCP\AppFramework\OCSController;
21+
use OCP\Conversion\IConversionManager;
22+
use OCP\Files\File;
23+
use OCP\Files\IRootFolder;
24+
use OCP\IRequest;
25+
26+
class ConversionApiController extends OCSController {
27+
public function __construct(
28+
string $appName,
29+
IRequest $request,
30+
private IConversionManager $conversionManager,
31+
private IRootFolder $rootFolder,
32+
private ?string $userId,
33+
) {
34+
parent::__construct($appName, $request);
35+
}
36+
37+
/**
38+
* Converts a file from one MIME type to another
39+
*
40+
* @param int $fileId ID of the file to be converted
41+
* @param string $targetMimeType The MIME type to which you want to convert the file
42+
* @param string|null $destination The target path of the converted file. Written to a temporary file if left empty
43+
*
44+
* @return DataResponse<Http::STATUS_CREATED, array{path: string}, array{}>
45+
*
46+
* 201: File was converted and written to the destination or temporary file
47+
*
48+
* @throws OCSException The file was unable to be converted
49+
* @throws OCSNotFoundException The file to be converted was not found
50+
*/
51+
#[NoAdminRequired]
52+
#[UserRateLimit(limit: 25, period: 120)]
53+
#[ApiRoute(verb: 'POST', url: '/convert', root: '/conversion')]
54+
public function convert(int $fileId, string $targetMimeType, ?string $destination = null): DataResponse {
55+
$userFolder = $this->rootFolder->getUserFolder($this->userId);
56+
$file = $userFolder->getFirstNodeById($fileId);
57+
58+
if (!($file instanceof File)) {
59+
throw new OCSNotFoundException();
60+
}
61+
62+
try {
63+
if ($destination !== null) {
64+
$destination = $userFolder->getFullpath($destination);
65+
}
66+
67+
$convertedFile = $this->conversionManager->convert($file, $targetMimeType, $destination);
68+
} catch (\Exception $e) {
69+
throw new OCSException($e->getMessage());
70+
}
71+
72+
return new DataResponse([
73+
'path' => $convertedFile,
74+
], Http::STATUS_CREATED);
75+
}
76+
}

core/openapi-ex_app.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"webdav-root",
3434
"reference-api",
3535
"reference-regex",
36+
"conversions",
3637
"mod-rewrite-working"
3738
],
3839
"properties": {
@@ -49,6 +50,12 @@
4950
"reference-regex": {
5051
"type": "string"
5152
},
53+
"conversions": {
54+
"type": "object",
55+
"additionalProperties": {
56+
"type": "object"
57+
}
58+
},
5259
"mod-rewrite-working": {
5360
"type": "boolean"
5461
}

core/openapi-full.json

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
"webdav-root",
100100
"reference-api",
101101
"reference-regex",
102+
"conversions",
102103
"mod-rewrite-working"
103104
],
104105
"properties": {
@@ -115,6 +116,12 @@
115116
"reference-regex": {
116117
"type": "string"
117118
},
119+
"conversions": {
120+
"type": "object",
121+
"additionalProperties": {
122+
"type": "object"
123+
}
124+
},
118125
"mod-rewrite-working": {
119126
"type": "boolean"
120127
}
@@ -2535,6 +2542,133 @@
25352542
}
25362543
}
25372544
},
2545+
"/ocs/v2.php/conversion/convert": {
2546+
"post": {
2547+
"operationId": "conversion_api-convert",
2548+
"summary": "Converts a file from one MIME type to another",
2549+
"tags": [
2550+
"conversion_api"
2551+
],
2552+
"security": [
2553+
{
2554+
"bearer_auth": []
2555+
},
2556+
{
2557+
"basic_auth": []
2558+
}
2559+
],
2560+
"requestBody": {
2561+
"required": true,
2562+
"content": {
2563+
"application/json": {
2564+
"schema": {
2565+
"type": "object",
2566+
"required": [
2567+
"fileId",
2568+
"targetMimeType"
2569+
],
2570+
"properties": {
2571+
"fileId": {
2572+
"type": "integer",
2573+
"format": "int64",
2574+
"description": "ID of the file to be converted"
2575+
},
2576+
"targetMimeType": {
2577+
"type": "string",
2578+
"description": "The MIME type to which you want to convert the file"
2579+
},
2580+
"destination": {
2581+
"type": "string",
2582+
"nullable": true,
2583+
"description": "The target path of the converted file. Written to a temporary file if left empty"
2584+
}
2585+
}
2586+
}
2587+
}
2588+
}
2589+
},
2590+
"parameters": [
2591+
{
2592+
"name": "OCS-APIRequest",
2593+
"in": "header",
2594+
"description": "Required to be true for the API request to pass",
2595+
"required": true,
2596+
"schema": {
2597+
"type": "boolean",
2598+
"default": true
2599+
}
2600+
}
2601+
],
2602+
"responses": {
2603+
"201": {
2604+
"description": "File was converted and written to the destination or temporary file",
2605+
"content": {
2606+
"application/json": {
2607+
"schema": {
2608+
"type": "object",
2609+
"required": [
2610+
"ocs"
2611+
],
2612+
"properties": {
2613+
"ocs": {
2614+
"type": "object",
2615+
"required": [
2616+
"meta",
2617+
"data"
2618+
],
2619+
"properties": {
2620+
"meta": {
2621+
"$ref": "#/components/schemas/OCSMeta"
2622+
},
2623+
"data": {
2624+
"type": "object",
2625+
"required": [
2626+
"path"
2627+
],
2628+
"properties": {
2629+
"path": {
2630+
"type": "string"
2631+
}
2632+
}
2633+
}
2634+
}
2635+
}
2636+
}
2637+
}
2638+
}
2639+
}
2640+
},
2641+
"404": {
2642+
"description": "The file to be converted was not found",
2643+
"content": {
2644+
"application/json": {
2645+
"schema": {
2646+
"type": "object",
2647+
"required": [
2648+
"ocs"
2649+
],
2650+
"properties": {
2651+
"ocs": {
2652+
"type": "object",
2653+
"required": [
2654+
"meta",
2655+
"data"
2656+
],
2657+
"properties": {
2658+
"meta": {
2659+
"$ref": "#/components/schemas/OCSMeta"
2660+
},
2661+
"data": {}
2662+
}
2663+
}
2664+
}
2665+
}
2666+
}
2667+
}
2668+
}
2669+
}
2670+
}
2671+
},
25382672
"/ocs/v2.php/hovercard/v1/{userId}": {
25392673
"get": {
25402674
"operationId": "hover_card-get-user",

0 commit comments

Comments
 (0)