S3.php 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OC\Files\ObjectStore;
  7. use Aws\Result;
  8. use Exception;
  9. use OCP\Files\ObjectStore\IObjectStore;
  10. use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
  11. class S3 implements IObjectStore, IObjectStoreMultiPartUpload {
  12. use S3ConnectionTrait;
  13. use S3ObjectTrait;
  14. public function __construct(array $parameters) {
  15. $parameters['primary_storage'] = true;
  16. $this->parseParams($parameters);
  17. }
  18. /**
  19. * @return string the container or bucket name where objects are stored
  20. * @since 7.0.0
  21. */
  22. public function getStorageId() {
  23. return $this->id;
  24. }
  25. public function initiateMultipartUpload(string $urn): string {
  26. $upload = $this->getConnection()->createMultipartUpload([
  27. 'Bucket' => $this->bucket,
  28. 'Key' => $urn,
  29. ] + $this->getSSECParameters());
  30. $uploadId = $upload->get('UploadId');
  31. if ($uploadId === null) {
  32. throw new Exception('No upload id returned');
  33. }
  34. return (string)$uploadId;
  35. }
  36. public function uploadMultipartPart(string $urn, string $uploadId, int $partId, $stream, $size): Result {
  37. return $this->getConnection()->uploadPart([
  38. 'Body' => $stream,
  39. 'Bucket' => $this->bucket,
  40. 'Key' => $urn,
  41. 'ContentLength' => $size,
  42. 'PartNumber' => $partId,
  43. 'UploadId' => $uploadId,
  44. ] + $this->getSSECParameters());
  45. }
  46. public function getMultipartUploads(string $urn, string $uploadId): array {
  47. $parts = [];
  48. $isTruncated = true;
  49. $partNumberMarker = 0;
  50. while ($isTruncated) {
  51. $result = $this->getConnection()->listParts([
  52. 'Bucket' => $this->bucket,
  53. 'Key' => $urn,
  54. 'UploadId' => $uploadId,
  55. 'MaxParts' => 1000,
  56. 'PartNumberMarker' => $partNumberMarker
  57. ] + $this->getSSECParameters());
  58. $parts = array_merge($parts, $result->get('Parts') ?? []);
  59. $isTruncated = $result->get('IsTruncated');
  60. $partNumberMarker = $result->get('NextPartNumberMarker');
  61. }
  62. return $parts;
  63. }
  64. public function completeMultipartUpload(string $urn, string $uploadId, array $result): int {
  65. $this->getConnection()->completeMultipartUpload([
  66. 'Bucket' => $this->bucket,
  67. 'Key' => $urn,
  68. 'UploadId' => $uploadId,
  69. 'MultipartUpload' => ['Parts' => $result],
  70. ] + $this->getSSECParameters());
  71. $stat = $this->getConnection()->headObject([
  72. 'Bucket' => $this->bucket,
  73. 'Key' => $urn,
  74. ] + $this->getSSECParameters());
  75. return (int)$stat->get('ContentLength');
  76. }
  77. public function abortMultipartUpload($urn, $uploadId): void {
  78. $this->getConnection()->abortMultipartUpload([
  79. 'Bucket' => $this->bucket,
  80. 'Key' => $urn,
  81. 'UploadId' => $uploadId
  82. ]);
  83. }
  84. }