Skip to content

Commit c9a4f01

Browse files
authored
Merge pull request #14273 from nextcloud/backport/14210/stable15
[stable15] Fix empty file uploads to S3 (and other streaming storages)
2 parents 6e110c3 + 7cc3486 commit c9a4f01

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

apps/dav/lib/Connector/Sabre/File.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
namespace OCA\DAV\Connector\Sabre;
3838

39+
use Icewind\Streams\CallbackWrapper;
3940
use OC\AppFramework\Http\Request;
4041
use OC\Files\Filesystem;
4142
use OC\Files\View;
@@ -166,10 +167,26 @@ public function put($data) {
166167
}
167168

168169
if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
169-
$count = $partStorage->writeStream($internalPartPath, $data);
170+
171+
if (!is_resource($data)) {
172+
$data = fopen('php://temp', 'r+');
173+
fwrite($data, 'foobar');
174+
rewind($data);
175+
}
176+
177+
$isEOF = false;
178+
$wrappedData = CallbackWrapper::wrap($data, null, null, null, null, function($stream) use (&$isEOF) {
179+
$isEOF = feof($stream);
180+
});
181+
182+
$count = $partStorage->writeStream($internalPartPath, $wrappedData);
170183
$result = $count > 0;
184+
171185
if ($result === false) {
172-
$result = feof($data);
186+
$result = $isEOF;
187+
if (is_resource($wrappedData)) {
188+
$result = feof($wrappedData);
189+
}
173190
}
174191

175192
} else {

lib/private/Files/ObjectStore/S3ObjectTrait.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323

2424
namespace OC\Files\ObjectStore;
2525

26+
use Aws\S3\Exception\S3MultipartUploadException;
2627
use Aws\S3\MultipartUploader;
28+
use Aws\S3\ObjectUploader;
2729
use Aws\S3\S3Client;
30+
use Icewind\Streams\CallbackWrapper;
2831

2932
const S3_UPLOAD_PART_SIZE = 524288000; // 500MB
3033

@@ -73,12 +76,30 @@ function readObject($urn) {
7376
* @since 7.0.0
7477
*/
7578
function writeObject($urn, $stream) {
76-
$uploader = new MultipartUploader($this->getConnection(), $stream, [
79+
$count = 0;
80+
$countStream = CallbackWrapper::wrap($stream, function ($read) use (&$count) {
81+
$count += $read;
82+
});
83+
84+
$uploader = new MultipartUploader($this->getConnection(), $countStream, [
7785
'bucket' => $this->bucket,
7886
'key' => $urn,
7987
'part_size' => S3_UPLOAD_PART_SIZE
8088
]);
81-
$uploader->upload();
89+
90+
try {
91+
$uploader->upload();
92+
} catch (S3MultipartUploadException $e) {
93+
// This is an emty file so just touch it then
94+
if ($count === 0 && feof($countStream)) {
95+
$uploader = new ObjectUploader($this->getConnection(), $this->bucket, $urn, '');
96+
$uploader->upload();
97+
} else {
98+
throw $e;
99+
}
100+
}
101+
102+
fclose($countStream);
82103
}
83104

84105
/**

0 commit comments

Comments
 (0)