aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2024-11-18 17:53:50 +0100
committerRobin Appelman <robin@icewind.nl>2024-12-05 14:07:40 +0100
commitca547bb913132195c0535acd94897458bd6d0c1d (patch)
treeb0194aa5cdebd30e52aef49df4678cb926c2663a /lib
parent7da8951c57b07d0ee90c16129367255e4217cb81 (diff)
downloadnextcloud-server-ca547bb913132195c0535acd94897458bd6d0c1d.tar.gz
nextcloud-server-ca547bb913132195c0535acd94897458bd6d0c1d.zip
fix: don't perform the extra buffering in s3 stream write when the stream size is known
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php33
1 files changed, 23 insertions, 10 deletions
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index dfe96294c69..9d7cfa644e6 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -140,20 +140,33 @@ trait S3ObjectTrait {
* @since 7.0.0
*/
public function writeObject($urn, $stream, ?string $mimetype = null) {
+ $canSeek = fseek($stream, 0, SEEK_CUR) === 0;
$psrStream = Utils::streamFor($stream);
- // ($psrStream->isSeekable() && $psrStream->getSize() !== null) evaluates to true for a On-Seekable stream
- // so the optimisation does not apply
- $buffer = new Psr7\Stream(fopen('php://temp', 'rwb+'));
- Utils::copyToStream($psrStream, $buffer, $this->putSizeLimit);
- $buffer->seek(0);
- if ($buffer->getSize() < $this->putSizeLimit) {
- // buffer is fully seekable, so use it directly for the small upload
- $this->writeSingle($urn, $buffer, $mimetype);
+
+ $size = $psrStream->getSize();
+ if ($size === null || !$canSeek) {
+ // The s3 single-part upload requires the size to be known for the stream.
+ // So for input streams that don't have a known size, we need to copy (part of)
+ // the input into a temporary stream so the size can be determined
+ $buffer = new Psr7\Stream(fopen('php://temp', 'rw+'));
+ Utils::copyToStream($psrStream, $buffer, $this->putSizeLimit);
+ $buffer->seek(0);
+ if ($buffer->getSize() < $this->putSizeLimit) {
+ // buffer is fully seekable, so use it directly for the small upload
+ $this->writeSingle($urn, $buffer, $mimetype);
+ } else {
+ $loadStream = new Psr7\AppendStream([$buffer, $psrStream]);
+ $this->writeMultiPart($urn, $loadStream, $mimetype);
+ }
} else {
- $loadStream = new Psr7\AppendStream([$buffer, $psrStream]);
- $this->writeMultiPart($urn, $loadStream, $mimetype);
+ if ($size < $this->putSizeLimit) {
+ $this->writeSingle($urn, $psrStream, $mimetype);
+ } else {
+ $this->writeMultiPart($urn, $psrStream, $mimetype);
+ }
}
+ $psrStream->close();
}
/**