Skip to content

Commit 9592390

Browse files
Merge pull request #51779 from nextcloud/object-store-filename
2 parents 24c6a1f + 8aae332 commit 9592390

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

lib/private/Files/ObjectStore/ObjectStoreStorage.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use OCP\Files\GenericFileException;
2323
use OCP\Files\NotFoundException;
2424
use OCP\Files\ObjectStore\IObjectStore;
25+
use OCP\Files\ObjectStore\IObjectStoreMetaData;
2526
use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
2627
use OCP\Files\Storage\IChunkedFileWrite;
2728
use OCP\Files\Storage\IStorage;
@@ -479,6 +480,11 @@ public function writeStream(string $path, $stream, ?int $size = null): int {
479480

480481
$mimetypeDetector = \OC::$server->getMimeTypeDetector();
481482
$mimetype = $mimetypeDetector->detectPath($path);
483+
$metadata = [
484+
'mimetype' => $mimetype,
485+
'original-storage' => $this->getId(),
486+
'original-path' => $path,
487+
];
482488

483489
$stat['mimetype'] = $mimetype;
484490
$stat['etag'] = $this->getETag($path);
@@ -507,13 +513,21 @@ public function writeStream(string $path, $stream, ?int $size = null): int {
507513
]);
508514
$size = $writtenSize;
509515
});
510-
$this->objectStore->writeObject($urn, $countStream, $mimetype);
516+
if ($this->objectStore instanceof IObjectStoreMetaData) {
517+
$this->objectStore->writeObjectWithMetaData($urn, $countStream, $metadata);
518+
} else {
519+
$this->objectStore->writeObject($urn, $countStream, $metadata['mimetype']);
520+
}
511521
if (is_resource($countStream)) {
512522
fclose($countStream);
513523
}
514524
$stat['size'] = $size;
515525
} else {
516-
$this->objectStore->writeObject($urn, $stream, $mimetype);
526+
if ($this->objectStore instanceof IObjectStoreMetaData) {
527+
$this->objectStore->writeObjectWithMetaData($urn, $stream, $metadata);
528+
} else {
529+
$this->objectStore->writeObject($urn, $stream, $metadata['mimetype']);
530+
}
517531
if (is_resource($stream)) {
518532
fclose($stream);
519533
}

lib/private/Files/ObjectStore/S3.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ public function abortMultipartUpload($urn, $uploadId): void {
9595
]);
9696
}
9797

98+
private function parseS3Metadata(array $metadata): array {
99+
$result = [];
100+
foreach ($metadata as $key => $value) {
101+
if (str_starts_with($key, 'x-amz-meta-')) {
102+
$result[substr($key, strlen('x-amz-meta-'))] = $value;
103+
}
104+
}
105+
return $result;
106+
}
107+
98108
public function getObjectMetaData(string $urn): array {
99109
$object = $this->getConnection()->headObject([
100110
'Bucket' => $this->bucket,
@@ -104,7 +114,7 @@ public function getObjectMetaData(string $urn): array {
104114
'mtime' => $object['LastModified'],
105115
'etag' => trim($object['ETag'], '"'),
106116
'size' => (int)($object['Size'] ?? $object['ContentLength']),
107-
];
117+
] + $this->parseS3Metadata($object['Metadata'] ?? []);
108118
}
109119

110120
public function listObjects(string $prefix = ''): \Iterator {

lib/private/Files/ObjectStore/S3ObjectTrait.php

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,32 @@ public function readObject($urn) {
7777
return $fh;
7878
}
7979

80+
private function buildS3Metadata(array $metadata): array {
81+
$result = [];
82+
foreach ($metadata as $key => $value) {
83+
$result['x-amz-meta-' . $key] = $value;
84+
}
85+
return $result;
86+
}
8087

8188
/**
8289
* Single object put helper
8390
*
8491
* @param string $urn the unified resource name used to identify the object
8592
* @param StreamInterface $stream stream with the data to write
86-
* @param string|null $mimetype the mimetype to set for the remove object @since 22.0.0
93+
* @param array $metaData the metadata to set for the object
8794
* @throws \Exception when something goes wrong, message will be logged
8895
*/
89-
protected function writeSingle(string $urn, StreamInterface $stream, ?string $mimetype = null): void {
96+
protected function writeSingle(string $urn, StreamInterface $stream, array $metaData): void {
97+
$mimetype = $metaData['mimetype'] ?? null;
98+
unset($metaData['mimetype']);
9099
$this->getConnection()->putObject([
91100
'Bucket' => $this->bucket,
92101
'Key' => $urn,
93102
'Body' => $stream,
94103
'ACL' => 'private',
95104
'ContentType' => $mimetype,
105+
'Metadata' => $this->buildS3Metadata($metaData),
96106
'StorageClass' => $this->storageClass,
97107
] + $this->getSSECParameters());
98108
}
@@ -103,17 +113,20 @@ protected function writeSingle(string $urn, StreamInterface $stream, ?string $mi
103113
*
104114
* @param string $urn the unified resource name used to identify the object
105115
* @param StreamInterface $stream stream with the data to write
106-
* @param string|null $mimetype the mimetype to set for the remove object
116+
* @param array $metaData the metadata to set for the object
107117
* @throws \Exception when something goes wrong, message will be logged
108118
*/
109-
protected function writeMultiPart(string $urn, StreamInterface $stream, ?string $mimetype = null): void {
119+
protected function writeMultiPart(string $urn, StreamInterface $stream, array $metaData): void {
120+
$mimetype = $metaData['mimetype'] ?? null;
121+
unset($metaData['mimetype']);
110122
$uploader = new MultipartUploader($this->getConnection(), $stream, [
111123
'bucket' => $this->bucket,
112124
'concurrency' => $this->concurrency,
113125
'key' => $urn,
114126
'part_size' => $this->uploadPartSize,
115127
'params' => [
116128
'ContentType' => $mimetype,
129+
'Metadata' => $this->buildS3Metadata($metaData),
117130
'StorageClass' => $this->storageClass,
118131
] + $this->getSSECParameters(),
119132
]);
@@ -131,15 +144,15 @@ protected function writeMultiPart(string $urn, StreamInterface $stream, ?string
131144
}
132145
}
133146

134-
135-
/**
136-
* @param string $urn the unified resource name used to identify the object
137-
* @param resource $stream stream with the data to write
138-
* @param string|null $mimetype the mimetype to set for the remove object @since 22.0.0
139-
* @throws \Exception when something goes wrong, message will be logged
140-
* @since 7.0.0
141-
*/
142147
public function writeObject($urn, $stream, ?string $mimetype = null) {
148+
$metaData = [];
149+
if ($mimetype) {
150+
$metaData['mimetype'] = $mimetype;
151+
}
152+
$this->writeObjectWithMetaData($urn, $stream, $metaData);
153+
}
154+
155+
public function writeObjectWithMetaData(string $urn, $stream, array $metaData): void {
143156
$canSeek = fseek($stream, 0, SEEK_CUR) === 0;
144157
$psrStream = Utils::streamFor($stream);
145158

@@ -154,16 +167,16 @@ public function writeObject($urn, $stream, ?string $mimetype = null) {
154167
$buffer->seek(0);
155168
if ($buffer->getSize() < $this->putSizeLimit) {
156169
// buffer is fully seekable, so use it directly for the small upload
157-
$this->writeSingle($urn, $buffer, $mimetype);
170+
$this->writeSingle($urn, $buffer, $metaData);
158171
} else {
159172
$loadStream = new Psr7\AppendStream([$buffer, $psrStream]);
160-
$this->writeMultiPart($urn, $loadStream, $mimetype);
173+
$this->writeMultiPart($urn, $loadStream, $metaData);
161174
}
162175
} else {
163176
if ($size < $this->putSizeLimit) {
164-
$this->writeSingle($urn, $psrStream, $mimetype);
177+
$this->writeSingle($urn, $psrStream, $metaData);
165178
} else {
166-
$this->writeMultiPart($urn, $psrStream, $mimetype);
179+
$this->writeMultiPart($urn, $psrStream, $metaData);
167180
}
168181
}
169182
$psrStream->close();

lib/public/Files/ObjectStore/IObjectStoreMetaData.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/**
1010
* Interface IObjectStoreMetaData
1111
*
12-
* @psalm-type ObjectMetaData = array{mtime?: \DateTime, etag?: string, size?: int, mimetype?: string, filename?: string}
12+
* @psalm-type ObjectMetaData = array{mtime?: \DateTime, etag?: string, size?: int, mimetype?: string, filename?: string, original-path?: string, original-storage?: string}
1313
*
1414
* @since 32.0.0
1515
*/
@@ -35,4 +35,13 @@ public function getObjectMetaData(string $urn): array;
3535
* @since 32.0.0
3636
*/
3737
public function listObjects(string $prefix = ''): \Iterator;
38+
39+
/**
40+
* @param string $urn the unified resource name used to identify the object
41+
* @param resource $stream stream with the data to write
42+
* @param ObjectMetaData $metaData the metadata to set for the object
43+
* @throws \Exception when something goes wrong, message will be logged
44+
* @since 32.0.0
45+
*/
46+
public function writeObjectWithMetaData(string $urn, $stream, array $metaData): void;
3847
}

0 commit comments

Comments
 (0)