66 */
77namespace OC \Files \ObjectStore ;
88
9+ use Aws \Command ;
10+ use Aws \Exception \MultipartUploadException ;
911use Aws \S3 \Exception \S3MultipartUploadException ;
1012use Aws \S3 \MultipartCopy ;
1113use Aws \S3 \MultipartUploader ;
@@ -87,14 +89,20 @@ public function readObject($urn) {
8789 * @throws \Exception when something goes wrong, message will be logged
8890 */
8991 protected function writeSingle (string $ urn , StreamInterface $ stream , array $ metaData ): void {
90- $ this -> getConnection ()-> putObject ( [
92+ $ args = [
9193 'Bucket ' => $ this ->bucket ,
9294 'Key ' => $ urn ,
9395 'Body ' => $ stream ,
9496 'ACL ' => 'private ' ,
9597 'ContentType ' => $ metaData ['mimetype ' ] ?? null ,
9698 'StorageClass ' => $ this ->storageClass ,
97- ] + $ this ->getSSECParameters ());
99+ ] + $ this ->getSSECParameters ();
100+
101+ if ($ size = $ stream ->getSize ()) {
102+ $ args ['ContentLength ' ] = $ size ;
103+ }
104+
105+ $ this ->getConnection ()->putObject ($ args );
98106 }
99107
100108
@@ -112,6 +120,8 @@ protected function writeMultiPart(string $urn, StreamInterface $stream, array $m
112120 $ concurrency = $ this ->concurrency ;
113121 $ exception = null ;
114122 $ state = null ;
123+ $ size = $ stream ->getSize ();
124+ $ totalWritten = 0 ;
115125
116126 // retry multipart upload once with concurrency at half on failure
117127 while (!$ uploaded && $ attempts <= 1 ) {
@@ -125,6 +135,15 @@ protected function writeMultiPart(string $urn, StreamInterface $stream, array $m
125135 'ContentType ' => $ metaData ['mimetype ' ] ?? null ,
126136 'StorageClass ' => $ this ->storageClass ,
127137 ] + $ this ->getSSECParameters (),
138+ 'before_upload ' => function (Command $ command ) use (&$ totalWritten ) {
139+ $ totalWritten += $ command ['ContentLength ' ];
140+ },
141+ 'before_complete ' => function ($ _command ) use (&$ totalWritten , $ size , &$ uploader , &$ attempts ) {
142+ if ($ size !== null && $ totalWritten != $ size ) {
143+ $ e = new \Exception ('Incomplete multi part upload, expected ' . $ size . ' bytes, wrote ' . $ totalWritten );
144+ throw new MultipartUploadException ($ uploader ->getState (), $ e );
145+ }
146+ },
128147 ]);
129148
130149 try {
@@ -141,6 +160,9 @@ protected function writeMultiPart(string $urn, StreamInterface $stream, array $m
141160 if ($ stream ->isSeekable ()) {
142161 $ stream ->rewind ();
143162 }
163+ } catch (MultipartUploadException $ e ) {
164+ $ exception = $ e ;
165+ break ;
144166 }
145167 }
146168
@@ -166,7 +188,9 @@ public function writeObject($urn, $stream, ?string $mimetype = null) {
166188
167189 public function writeObjectWithMetaData (string $ urn , $ stream , array $ metaData ): void {
168190 $ canSeek = fseek ($ stream , 0 , SEEK_CUR ) === 0 ;
169- $ psrStream = Utils::streamFor ($ stream );
191+ $ psrStream = Utils::streamFor ($ stream , [
192+ 'size ' => $ metaData ['size ' ] ?? null ,
193+ ]);
170194
171195
172196 $ size = $ psrStream ->getSize ();
0 commit comments