2020-01-12 21:28:26 +00:00
< ? php
namespace Tests\E2E\Services\Storage ;
2023-08-23 20:42:16 +00:00
use Appwrite\Extend\Exception ;
2020-01-12 21:28:26 +00:00
use CURLFile ;
2026-01-15 03:14:53 +00:00
use PHPUnit\Framework\Attributes\Group ;
2020-01-12 21:28:26 +00:00
use Tests\E2E\Client ;
2022-12-14 15:42:25 +00:00
use Utopia\Database\Helpers\ID ;
2022-12-14 16:04:06 +00:00
use Utopia\Database\Helpers\Permission ;
use Utopia\Database\Helpers\Role ;
2023-12-20 10:55:09 +00:00
use Utopia\Database\Query ;
2023-03-01 12:00:36 +00:00
use Utopia\Database\Validator\Datetime as DatetimeValidator ;
2020-01-12 21:28:26 +00:00
trait StorageBase
{
2026-02-05 22:54:14 +00:00
/**
* @ var array Cached bucket and file data for tests
*/
private static array $cachedBucketFile = [];
/**
* @ var array Cached zstd compression bucket data for tests
*/
private static array $cachedZstdBucket = [];
/**
* Helper method to set up bucket and file data for tests .
* Uses static caching to avoid recreating resources .
*/
protected function setupBucketFile () : array
{
$cacheKey = $this -> getProject ()[ '$id' ];
if ( ! empty ( self :: $cachedBucketFile [ $cacheKey ])) {
return self :: $cachedBucketFile [ $cacheKey ];
}
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket' ,
'fileSecurity' => true ,
'maximumFileSize' => 2000000 , //2MB
'allowedFileExtensions' => [ 'jpg' , 'png' , 'jfif' , 'webp' ],
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$bucketId = $bucket [ 'body' ][ '$id' ];
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
// Create large file bucket
$bucket2 = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket 2' ,
'fileSecurity' => true ,
'permissions' => [
Permission :: create ( Role :: any ()),
],
]);
// Chunked Upload for large file
$source = __DIR__ . " /../../../resources/disk-a/large-file.mp4 " ;
$totalSize = \filesize ( $source );
$chunkSize = 5 * 1024 * 1024 ;
$handle = @ fopen ( $source , " rb " );
$fileId = 'unique()' ;
$mimeType = mime_content_type ( $source );
$counter = 0 ;
$size = filesize ( $source );
$headers = [
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ]
];
$id = '' ;
2026-04-01 04:50:20 +00:00
$largeFile = null ;
2026-02-05 22:54:14 +00:00
while ( ! feof ( $handle )) {
$curlFile = new \CURLFile ( 'data://' . $mimeType . ';base64,' . base64_encode ( @ fread ( $handle , $chunkSize )), $mimeType , 'large-file.mp4' );
$headers [ 'content-range' ] = 'bytes ' . ( $counter * $chunkSize ) . '-' . min (((( $counter * $chunkSize ) + $chunkSize ) - 1 ), $size - 1 ) . '/' . $size ;
if ( ! empty ( $id )) {
$headers [ 'x-appwrite-id' ] = $id ;
}
$largeFile = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucket2 [ 'body' ][ '$id' ] . '/files' , array_merge ( $headers , $this -> getHeaders ()), [
'fileId' => $fileId ,
'file' => $curlFile ,
'permissions' => [
Permission :: read ( Role :: any ())
],
]);
$counter ++ ;
$id = $largeFile [ 'body' ][ '$id' ];
}
@ fclose ( $handle );
// Upload webp file
$webpFile = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/image.webp' ), 'image/webp' , 'image.webp' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
self :: $cachedBucketFile [ $cacheKey ] = [
'bucketId' => $bucketId ,
'fileId' => $file [ 'body' ][ '$id' ],
2026-04-01 04:50:20 +00:00
'largeFileId' => $largeFile [ 'body' ][ '$id' ] ? ? '' ,
2026-02-05 22:54:14 +00:00
'largeBucketId' => $bucket2 [ 'body' ][ '$id' ],
'webpFileId' => $webpFile [ 'body' ][ '$id' ]
];
return self :: $cachedBucketFile [ $cacheKey ];
}
/**
* Helper method to set up zstd compression bucket for tests .
* Uses static caching to avoid recreating resources .
*/
protected function setupZstdCompressionBucket () : array
{
$cacheKey = $this -> getProject ()[ '$id' ];
if ( ! empty ( self :: $cachedZstdBucket [ $cacheKey ])) {
return self :: $cachedZstdBucket [ $cacheKey ];
}
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket' ,
'fileSecurity' => true ,
'maximumFileSize' => 2000000 , //2MB
'allowedFileExtensions' => [ " jpg " , " png " ],
'compression' => 'zstd' ,
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
self :: $cachedZstdBucket [ $cacheKey ] = [ 'bucketId' => $bucket [ 'body' ][ '$id' ]];
return self :: $cachedZstdBucket [ $cacheKey ];
}
2026-01-15 03:14:53 +00:00
#[Group('fileTokens')]
2026-02-05 22:54:14 +00:00
public function testCreateBucketFile () : void
2021-06-17 10:10:58 +00:00
{
/**
* Test for SUCCESS
*/
2022-02-16 08:30:09 +00:00
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
2021-06-17 10:10:58 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2021-06-21 07:06:28 +00:00
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
2022-02-16 08:30:09 +00:00
], [
2022-08-14 10:33:36 +00:00
'bucketId' => ID :: unique (),
2021-06-17 10:10:58 +00:00
'name' => 'Test Bucket' ,
2022-08-03 04:17:49 +00:00
'fileSecurity' => true ,
2021-06-21 07:06:28 +00:00
'maximumFileSize' => 2000000 , //2MB
2025-10-30 22:26:30 +00:00
'allowedFileExtensions' => [ 'jpg' , 'png' , 'jfif' , 'webp' ],
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-17 10:10:58 +00:00
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $bucket [ 'body' ][ '$id' ]);
2021-06-21 07:06:28 +00:00
2021-06-17 10:10:58 +00:00
$bucketId = $bucket [ 'body' ][ '$id' ];
2021-06-21 07:06:28 +00:00
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
2021-06-17 10:10:58 +00:00
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: unique (),
2021-06-17 10:10:58 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-17 10:10:58 +00:00
]);
2021-06-18 08:38:36 +00:00
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
2021-06-17 10:10:58 +00:00
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
2022-12-19 11:21:09 +00:00
$dateValidator = new DatetimeValidator ();
$this -> assertEquals ( true , $dateValidator -> isValid ( $file [ 'body' ][ '$createdAt' ]));
2021-06-17 10:10:58 +00:00
$this -> assertEquals ( 'logo.png' , $file [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'image/png' , $file [ 'body' ][ 'mimeType' ]);
$this -> assertEquals ( 47218 , $file [ 'body' ][ 'sizeOriginal' ]);
2023-05-10 06:31:12 +00:00
$this -> assertTrue ( md5_file ( realpath ( __DIR__ . '/../../../resources/logo.png' )) == $file [ 'body' ][ 'signature' ]);
2021-06-21 08:23:08 +00:00
/**
* Test for Large File above 20 MB
* This should also validate the test for when Bucket encryption
* is disabled as we are using same test
*/
2022-02-16 08:30:09 +00:00
$bucket2 = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
2021-06-21 08:23:08 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
2022-02-16 08:30:09 +00:00
], [
2022-08-14 10:33:36 +00:00
'bucketId' => ID :: unique (),
2021-06-21 08:23:08 +00:00
'name' => 'Test Bucket 2' ,
2022-08-03 04:17:49 +00:00
'fileSecurity' => true ,
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: create ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-21 08:23:08 +00:00
]);
$this -> assertEquals ( 201 , $bucket2 [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $bucket2 [ 'body' ][ '$id' ]);
2022-03-15 09:51:51 +00:00
2021-07-07 10:07:11 +00:00
/**
* Chunked Upload
*/
$source = __DIR__ . " /../../../resources/disk-a/large-file.mp4 " ;
$totalSize = \filesize ( $source );
2022-05-23 14:54:50 +00:00
$chunkSize = 5 * 1024 * 1024 ;
2021-07-07 10:07:11 +00:00
$handle = @ fopen ( $source , " rb " );
2021-09-08 08:02:05 +00:00
$fileId = 'unique()' ;
2021-07-27 11:02:53 +00:00
$mimeType = mime_content_type ( $source );
$counter = 0 ;
$size = filesize ( $source );
2021-09-27 06:36:34 +00:00
$headers = [
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ]
];
$id = '' ;
2026-04-01 04:50:20 +00:00
$largeFile = null ;
2021-07-27 11:02:53 +00:00
while ( ! feof ( $handle )) {
$curlFile = new \CURLFile ( 'data://' . $mimeType . ';base64,' . base64_encode ( @ fread ( $handle , $chunkSize )), $mimeType , 'large-file.mp4' );
2023-04-19 04:44:59 +00:00
$headers [ 'content-range' ] = 'bytes ' . ( $counter * $chunkSize ) . '-' . min (((( $counter * $chunkSize ) + $chunkSize ) - 1 ), $size - 1 ) . '/' . $size ;
2022-05-23 14:54:50 +00:00
if ( ! empty ( $id )) {
2021-09-27 06:36:34 +00:00
$headers [ 'x-appwrite-id' ] = $id ;
}
$largeFile = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucket2 [ 'body' ][ '$id' ] . '/files' , array_merge ( $headers , $this -> getHeaders ()), [
2021-09-08 08:02:05 +00:00
'fileId' => $fileId ,
2021-07-07 10:07:11 +00:00
'file' => $curlFile ,
2022-08-03 04:17:49 +00:00
'permissions' => [
2023-12-25 06:06:18 +00:00
Permission :: read ( Role :: any ())
2022-08-03 04:17:49 +00:00
],
2021-07-07 10:07:11 +00:00
]);
2021-07-27 11:02:53 +00:00
$counter ++ ;
2021-09-27 06:36:34 +00:00
$id = $largeFile [ 'body' ][ '$id' ];
2021-07-07 10:07:11 +00:00
}
@ fclose ( $handle );
2022-03-15 09:51:51 +00:00
2021-07-07 10:07:11 +00:00
$this -> assertEquals ( 201 , $largeFile [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $largeFile [ 'body' ][ '$id' ]);
2022-12-19 11:21:09 +00:00
$this -> assertEquals ( true , $dateValidator -> isValid ( $largeFile [ 'body' ][ '$createdAt' ]));
2021-07-07 10:07:11 +00:00
$this -> assertEquals ( 'large-file.mp4' , $largeFile [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'video/mp4' , $largeFile [ 'body' ][ 'mimeType' ]);
$this -> assertEquals ( $totalSize , $largeFile [ 'body' ][ 'sizeOriginal' ]);
$this -> assertEquals ( md5_file ( realpath ( __DIR__ . '/../../../resources/disk-a/large-file.mp4' )), $largeFile [ 'body' ][ 'signature' ]); // should validate that the file is not encrypted
2022-03-15 09:51:51 +00:00
2022-01-16 07:32:39 +00:00
/**
* Failure
2024-05-03 12:31:15 +00:00
* Test for Chunk above 10 MB
2022-01-16 07:32:39 +00:00
*/
$source = __DIR__ . " /../../../resources/disk-a/large-file.mp4 " ;
$totalSize = \filesize ( $source );
2024-05-03 12:31:15 +00:00
$chunkSize = 12 * 1024 * 1024 ;
2022-01-16 07:32:39 +00:00
$handle = @ fopen ( $source , " rb " );
$fileId = 'unique()' ;
$mimeType = mime_content_type ( $source );
$counter = 0 ;
$size = filesize ( $source );
$headers = [
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ]
];
$id = '' ;
$curlFile = new \CURLFile ( 'data://' . $mimeType . ';base64,' . base64_encode ( @ fread ( $handle , $chunkSize )), $mimeType , 'large-file.mp4' );
2023-04-19 04:44:59 +00:00
$headers [ 'content-range' ] = 'bytes ' . ( $counter * $chunkSize ) . '-' . min (((( $counter * $chunkSize ) + $chunkSize ) - 1 ), $size - 1 ) . '/' . $size ;
2022-05-23 14:54:50 +00:00
$res = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucket2 [ 'body' ][ '$id' ] . '/files' , $this -> getHeaders (), [
2022-01-16 07:32:39 +00:00
'fileId' => $fileId ,
'file' => $curlFile ,
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2022-01-16 07:32:39 +00:00
]);
@ fclose ( $handle );
2022-03-15 09:51:51 +00:00
2022-01-16 11:25:26 +00:00
$this -> assertEquals ( 413 , $res [ 'headers' ][ 'status-code' ]);
2022-03-15 09:51:51 +00:00
2021-06-17 10:10:58 +00:00
/**
2021-06-21 06:58:06 +00:00
* Test for FAILURE unknown Bucket
2021-06-17 10:10:58 +00:00
*/
2021-06-21 06:58:06 +00:00
$res = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/empty/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: unique (),
2021-06-21 06:58:06 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-21 06:58:06 +00:00
]);
$this -> assertEquals ( 404 , $res [ 'headers' ][ 'status-code' ]);
2021-06-21 07:06:28 +00:00
/**
2021-06-22 12:12:46 +00:00
* Test for FAILURE file above bucket ' s file size limit
2021-06-21 07:06:28 +00:00
*/
$res = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: unique (),
2021-06-21 07:06:28 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/disk-b/kitten-1.png' ), 'image/png' , 'kitten-1.png' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-21 07:06:28 +00:00
]);
$this -> assertEquals ( 400 , $res [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'File size not allowed' , $res [ 'body' ][ 'message' ]);
/**
2021-06-22 12:12:46 +00:00
* Test for FAILURE unsupported bucket file extension
2021-06-21 07:06:28 +00:00
*/
2021-06-22 12:12:46 +00:00
$res = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: unique (),
2021-06-22 12:12:46 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/disk-a/kitten-3.gif' ), 'image/gif' , 'kitten-3.gif' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2021-06-22 12:12:46 +00:00
]);
$this -> assertEquals ( 400 , $res [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'File extension not allowed' , $res [ 'body' ][ 'message' ]);
2022-03-31 13:10:30 +00:00
/**
* Test for FAILURE create bucket with too high limit ( bigger then _APP_STORAGE_LIMIT )
*/
$failedBucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
2022-08-14 10:33:36 +00:00
'bucketId' => ID :: unique (),
2022-03-31 13:10:30 +00:00
'name' => 'Test Bucket 2' ,
2022-08-03 04:17:49 +00:00
'fileSecurity' => true ,
2024-06-18 06:29:47 +00:00
'maximumFileSize' => 6000000000 , //6GB
2022-03-31 13:10:30 +00:00
'allowedFileExtensions' => [ " jpg " , " png " ],
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2022-03-31 13:10:30 +00:00
]);
2022-08-09 07:11:30 +00:00
2022-03-31 13:10:30 +00:00
$this -> assertEquals ( 400 , $failedBucket [ 'headers' ][ 'status-code' ]);
2022-08-09 07:11:30 +00:00
2023-05-21 15:43:26 +00:00
/**
* Test for FAILURE set x - appwrite - id to unique ()
*/
$source = realpath ( __DIR__ . '/../../../resources/logo.png' );
$totalSize = \filesize ( $source );
$res = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2023-05-27 17:09:00 +00:00
'content-range' => 'bytes 0-' . $size . '/' . $size ,
2023-05-21 15:43:26 +00:00
'x-appwrite-id' => 'unique()' ,
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( $source , 'image/png' , 'logo.png' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 400 , $res [ 'headers' ][ 'status-code' ]);
2023-08-23 20:42:16 +00:00
$this -> assertEquals ( Exception :: STORAGE_INVALID_APPWRITE_ID , $res [ 'body' ][ 'type' ]);
2023-05-21 15:43:26 +00:00
2025-10-30 22:26:30 +00:00
/**
* Test for SUCCESS - Upload and view webp image
*/
$webpFile = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
2025-11-05 19:30:21 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/image.webp' ), 'image/webp' , 'image.webp' ),
2025-10-30 22:26:30 +00:00
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $webpFile [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $webpFile [ 'body' ][ '$id' ]);
2025-11-05 19:30:21 +00:00
$this -> assertEquals ( 'image.webp' , $webpFile [ 'body' ][ 'name' ]);
2025-10-30 22:26:30 +00:00
$this -> assertEquals ( 'image/webp' , $webpFile [ 'body' ][ 'mimeType' ]);
$webpFileId = $webpFile [ 'body' ][ '$id' ];
// View webp file
$webpView = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $webpFileId . '/view' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $webpView [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/webp' , $webpView [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $webpView [ 'body' ]);
2021-06-18 09:24:16 +00:00
}
2026-02-05 22:54:14 +00:00
public function testCreateBucketFileZstdCompression () : void
2022-08-31 02:49:13 +00:00
{
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket' ,
'fileSecurity' => true ,
'maximumFileSize' => 2000000 , //2MB
'allowedFileExtensions' => [ " jpg " , " png " ],
'compression' => 'zstd' ,
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $bucket [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'zstd' , $bucket [ 'body' ][ 'compression' ]);
$bucketId = $bucket [ 'body' ][ '$id' ];
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
2023-02-05 20:39:41 +00:00
$this -> assertEquals ( true , ( new DatetimeValidator ()) -> isValid ( $file [ 'body' ][ '$createdAt' ]));
2022-08-31 02:49:13 +00:00
$this -> assertEquals ( 'logo.png' , $file [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'image/png' , $file [ 'body' ][ 'mimeType' ]);
$this -> assertEquals ( 47218 , $file [ 'body' ][ 'sizeOriginal' ]);
2023-05-10 06:31:12 +00:00
$this -> assertTrue ( md5_file ( realpath ( __DIR__ . '/../../../resources/logo.png' )) == $file [ 'body' ][ 'signature' ]);
2022-08-31 02:49:13 +00:00
}
2023-08-22 17:11:32 +00:00
public function testCreateBucketFileNoCollidingId () : void
{
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket' ,
'maximumFileSize' => 2000000 , //2MB
'allowedFileExtensions' => [ " jpg " , " png " ],
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $bucket [ 'body' ][ '$id' ]);
$bucketId = $bucket [ 'body' ][ '$id' ];
$fileId = ID :: unique ();
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => $fileId ,
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $fileId , $file [ 'body' ][ '$id' ]);
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => $fileId ,
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/file.png' ), 'image/png' , 'file.png' ),
]);
$this -> assertEquals ( 409 , $file [ 'headers' ][ 'status-code' ]);
}
2026-02-05 22:54:14 +00:00
public function testListBucketFiles () : void
2021-06-18 09:24:16 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupBucketFile ();
2021-06-18 09:24:16 +00:00
/**
* Test for SUCCESS
*/
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $files [ 'headers' ][ 'status-code' ]);
2022-02-27 09:57:09 +00:00
$this -> assertGreaterThan ( 0 , $files [ 'body' ][ 'total' ]);
2021-06-18 09:24:16 +00:00
$this -> assertGreaterThan ( 0 , count ( $files [ 'body' ][ 'files' ]));
2025-10-20 15:18:17 +00:00
/**
2025-10-29 09:08:08 +00:00
* Test for SUCCESS with total = false
2025-10-20 15:18:17 +00:00
*/
$filesWithIncludeTotalFalse = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2025-10-29 09:08:08 +00:00
'total' => false
2025-10-20 15:18:17 +00:00
]);
2025-10-20 15:38:14 +00:00
$this -> assertEquals ( 200 , $filesWithIncludeTotalFalse [ 'headers' ][ 'status-code' ]);
2025-10-20 15:18:17 +00:00
$this -> assertIsArray ( $filesWithIncludeTotalFalse [ 'body' ]);
$this -> assertIsArray ( $filesWithIncludeTotalFalse [ 'body' ][ 'files' ]);
$this -> assertIsInt ( $filesWithIncludeTotalFalse [ 'body' ][ 'total' ]);
$this -> assertEquals ( 0 , $filesWithIncludeTotalFalse [ 'body' ][ 'total' ]);
$this -> assertGreaterThan ( 0 , count ( $filesWithIncludeTotalFalse [ 'body' ][ 'files' ]));
2022-08-24 11:55:43 +00:00
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: limit ( 1 ) -> toString (),
],
2022-08-24 11:55:43 +00:00
]);
$this -> assertEquals ( 200 , $files [ 'headers' ][ 'status-code' ]);
2023-05-03 11:53:40 +00:00
$this -> assertEquals ( 1 , count ( $files [ 'body' ][ 'files' ]));
2022-08-24 11:55:43 +00:00
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: offset ( 1 ) -> toString (),
],
2022-08-24 11:55:43 +00:00
]);
$this -> assertEquals ( 200 , $files [ 'headers' ][ 'status-code' ]);
2025-11-03 18:13:21 +00:00
$this -> assertEquals ( 1 , count ( $files [ 'body' ][ 'files' ]));
2022-08-24 11:55:43 +00:00
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: equal ( 'mimeType' , [ 'image/png' ]) -> toString (),
],
2022-08-24 11:55:43 +00:00
]);
$this -> assertEquals ( 200 , $files [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 1 , count ( $files [ 'body' ][ 'files' ]));
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-12-20 10:55:09 +00:00
'queries' => [
Query :: equal ( 'mimeType' , [ 'image/jpeg' ]) -> toString (),
],
2022-08-24 11:55:43 +00:00
]);
$this -> assertEquals ( 200 , $files [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , count ( $files [ 'body' ][ 'files' ]));
2021-06-18 09:24:16 +00:00
/**
2021-06-21 06:58:06 +00:00
* Test for FAILURE unknown Bucket
2021-06-18 09:24:16 +00:00
*/
2021-06-21 07:06:28 +00:00
2021-06-21 06:58:06 +00:00
$files = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/empty/files' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $files [ 'headers' ][ 'status-code' ]);
2021-06-17 10:10:58 +00:00
}
2021-06-18 09:33:00 +00:00
2026-02-05 22:54:14 +00:00
public function testGetBucketFile () : void
2021-06-18 09:33:00 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupBucketFile ();
2021-06-21 06:58:06 +00:00
$bucketId = $data [ 'bucketId' ];
2021-06-18 09:33:00 +00:00
/**
* Test for SUCCESS
*/
2021-06-21 06:58:06 +00:00
$file1 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ], array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file1 [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file1 [ 'body' ][ '$id' ]);
2023-02-05 20:39:41 +00:00
$this -> assertEquals ( true , ( new DatetimeValidator ()) -> isValid ( $file1 [ 'body' ][ '$createdAt' ]));
2021-06-18 09:33:00 +00:00
$this -> assertEquals ( 'logo.png' , $file1 [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'image/png' , $file1 [ 'body' ][ 'mimeType' ]);
$this -> assertEquals ( 47218 , $file1 [ 'body' ][ 'sizeOriginal' ]);
2022-08-02 09:19:15 +00:00
$this -> assertIsArray ( $file1 [ 'body' ][ '$permissions' ]);
2022-08-13 14:10:28 +00:00
$this -> assertCount ( 3 , $file1 [ 'body' ][ '$permissions' ]);
2021-06-18 09:33:00 +00:00
2021-06-21 06:58:06 +00:00
$file2 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/preview' , array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file2 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file2 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file2 [ 'body' ]);
2021-06-21 07:06:28 +00:00
2023-12-28 02:22:05 +00:00
// upload JXL file for preview
$fileJfif = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/disk-a/preview-test.jfif' ), 'image/jxl' , 'preview-test.jfif' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $fileJfif [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $fileJfif [ 'body' ][ '$id' ]);
// TEST preview JXL
$preview = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileJfif [ 'body' ][ '$id' ] . '/preview' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $preview [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/jpeg' , $preview [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $preview [ 'body' ]);
2021-06-18 09:33:00 +00:00
//new image preview features
2021-06-21 06:58:06 +00:00
$file3 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/preview' , array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 100 ,
'borderRadius' => '50' ,
'opacity' => '0.5' ,
'output' => 'png' ,
'rotation' => '45' ,
]);
$this -> assertEquals ( 200 , $file3 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file3 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file3 [ 'body' ]);
$image = new \Imagick ();
$image -> readImageBlob ( $file3 [ 'body' ]);
$original = new \Imagick ( __DIR__ . '/../../../resources/logo-after.png' );
$this -> assertEquals ( $image -> getImageWidth (), $original -> getImageWidth ());
$this -> assertEquals ( $image -> getImageHeight (), $original -> getImageHeight ());
$this -> assertEquals ( 'PNG' , $image -> getImageFormat ());
2021-06-21 06:58:06 +00:00
$file4 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/preview' , array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 200 ,
'height' => 80 ,
'borderWidth' => '5' ,
'borderColor' => 'ff0000' ,
'output' => 'jpg' ,
]);
2021-06-21 07:06:28 +00:00
2021-06-18 09:33:00 +00:00
$this -> assertEquals ( 200 , $file4 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/jpeg' , $file4 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file4 [ 'body' ]);
2021-06-21 07:06:28 +00:00
2021-06-18 09:33:00 +00:00
$image = new \Imagick ();
$image -> readImageBlob ( $file4 [ 'body' ]);
$original = new \Imagick ( __DIR__ . '/../../../resources/logo-after.jpg' );
$this -> assertEquals ( $image -> getImageWidth (), $original -> getImageWidth ());
$this -> assertEquals ( $image -> getImageHeight (), $original -> getImageHeight ());
$this -> assertEquals ( 'JPEG' , $image -> getImageFormat ());
2021-06-21 06:58:06 +00:00
$file5 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/download' , array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file5 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'attachment; filename="logo.png"' , $file5 [ 'headers' ][ 'content-disposition' ]);
$this -> assertEquals ( 'image/png' , $file5 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file5 [ 'body' ]);
2021-09-12 08:50:43 +00:00
// Test ranged download
$file51 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/download' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'Range' => 'bytes=0-99' ,
], $this -> getHeaders ()));
$path = __DIR__ . '/../../../resources/logo.png' ;
$originalChunk = \file_get_contents ( $path , false , null , 0 , 100 );
$this -> assertEquals ( 206 , $file51 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'attachment; filename="logo.png"' , $file51 [ 'headers' ][ 'content-disposition' ]);
$this -> assertEquals ( 'image/png' , $file51 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file51 [ 'body' ]);
$this -> assertEquals ( $originalChunk , $file51 [ 'body' ]);
2022-05-23 14:54:50 +00:00
2021-09-12 09:29:40 +00:00
// Test ranged download - with invalid range
$file52 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/download' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'Range' => 'bytes=0-' ,
], $this -> getHeaders ()));
2021-09-13 06:22:27 +00:00
$this -> assertEquals ( 206 , $file52 [ 'headers' ][ 'status-code' ]);
2022-05-23 14:54:50 +00:00
2021-09-12 09:29:40 +00:00
// Test ranged download - with invalid range
$file53 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/download' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'Range' => 'bytes=988' ,
], $this -> getHeaders ()));
2022-05-23 14:54:50 +00:00
2021-09-13 06:22:27 +00:00
$this -> assertEquals ( 416 , $file53 [ 'headers' ][ 'status-code' ]);
2022-05-23 14:54:50 +00:00
2021-09-12 09:29:40 +00:00
// Test ranged download - with invalid range
$file54 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/download' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'Range' => 'bytes=-988' ,
], $this -> getHeaders ()));
2022-05-23 14:54:50 +00:00
2021-09-13 06:22:27 +00:00
$this -> assertEquals ( 416 , $file54 [ 'headers' ][ 'status-code' ]);
2022-05-23 14:54:50 +00:00
2021-06-21 06:58:06 +00:00
$file6 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/view' , array_merge ([
2021-06-18 09:33:00 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file6 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file6 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file6 [ 'body' ]);
2021-11-11 14:11:56 +00:00
// Test for negative angle values in fileGetPreview
2021-12-08 09:10:13 +00:00
$file7 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $data [ 'fileId' ] . '/preview' , array_merge ([
2021-11-11 14:11:56 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 100 ,
'borderRadius' => '50' ,
'opacity' => '0.5' ,
'output' => 'png' ,
'rotation' => '-315' ,
]);
2022-05-23 14:54:50 +00:00
2021-11-11 14:11:56 +00:00
$this -> assertEquals ( 200 , $file7 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file7 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file7 [ 'body' ]);
$image = new \Imagick ();
$image -> readImageBlob ( $file7 [ 'body' ]);
$original = new \Imagick ( __DIR__ . '/../../../resources/logo-after.png' );
$this -> assertEquals ( $image -> getImageWidth (), $original -> getImageWidth ());
$this -> assertEquals ( $image -> getImageHeight (), $original -> getImageHeight ());
$this -> assertEquals ( 'PNG' , $image -> getImageFormat ());
2021-06-22 08:37:04 +00:00
/**
* Test large files decompress successfully
*/
$file7 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'largeBucketId' ] . '/files/' . $data [ 'largeFileId' ] . '/download' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$fileData = $file7 [ 'body' ];
$this -> assertEquals ( 200 , $file7 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'attachment; filename="large-file.mp4"' , $file7 [ 'headers' ][ 'content-disposition' ]);
$this -> assertEquals ( 'video/mp4' , $file7 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $fileData );
$this -> assertEquals ( md5_file ( realpath ( __DIR__ . '/../../../resources/disk-a/large-file.mp4' )), md5 ( $fileData )); // validate the file is downloaded correctly
2021-06-18 09:33:00 +00:00
/**
2021-06-21 06:58:06 +00:00
* Test for FAILURE unknown Bucket
2021-06-18 09:33:00 +00:00
*/
2021-06-22 08:37:04 +00:00
$file8 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/empty/files/' . $data [ 'fileId' ], array_merge ([
2021-06-21 06:58:06 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
2021-08-09 13:08:44 +00:00
], $this -> getHeaders ()), [
'limit' => 2
]);
2021-06-21 06:58:06 +00:00
2021-06-22 08:37:04 +00:00
$this -> assertEquals ( 404 , $file8 [ 'headers' ][ 'status-code' ]);
2021-06-18 09:33:00 +00:00
}
2021-06-20 11:20:35 +00:00
2026-02-05 22:54:14 +00:00
public function testFilePreviewCache () : void
2022-01-25 08:25:58 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupBucketFile ();
2022-01-25 08:25:58 +00:00
$bucketId = $data [ 'bucketId' ];
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: custom ( 'testcache' ),
2022-01-25 08:25:58 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2022-01-25 08:25:58 +00:00
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
2022-05-23 14:54:50 +00:00
2022-01-25 08:25:58 +00:00
$fileId = $file [ 'body' ][ '$id' ];
//get image preview
$file3 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 100 ,
'borderRadius' => '50' ,
'opacity' => '0.5' ,
'output' => 'png' ,
'rotation' => '45' ,
]);
$this -> assertEquals ( 200 , $file3 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file3 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file3 [ 'body' ]);
$imageBefore = new \Imagick ();
$imageBefore -> readImageBlob ( $file3 [ 'body' ]);
$file = $this -> client -> call ( Client :: METHOD_DELETE , '/storage/buckets/' . $data [ 'bucketId' ] . '/files/' . $fileId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $file [ 'body' ]);
2026-02-24 01:00:07 +00:00
$this -> assertEventually ( function () use ( $data , $fileId ) {
$file = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files/' . $fileId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $file [ 'headers' ][ 'status-code' ]);
}, 10_000 , 500 );
2022-01-25 08:25:58 +00:00
//upload again using the same ID
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-14 10:33:36 +00:00
'fileId' => ID :: custom ( 'testcache' ),
2022-01-27 07:21:32 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/disk-b/kitten-2.png' ), 'image/png' , 'logo.png' ),
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-14 05:21:11 +00:00
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
2022-08-03 04:17:49 +00:00
],
2022-01-25 08:25:58 +00:00
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
2022-05-23 14:54:50 +00:00
2022-01-25 08:25:58 +00:00
//get image preview after
$file3 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 100 ,
'borderRadius' => '50' ,
'opacity' => '0.5' ,
'output' => 'png' ,
'rotation' => '45' ,
]);
$this -> assertEquals ( 200 , $file3 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file3 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file3 [ 'body' ]);
$imageAfter = new \Imagick ();
$imageAfter -> readImageBlob ( $file3 [ 'body' ]);
2022-01-27 07:34:47 +00:00
$this -> assertNotEquals ( $imageBefore -> getImageBlob (), $imageAfter -> getImageBlob ());
2022-01-25 08:25:58 +00:00
}
2026-02-05 22:54:14 +00:00
public function testFilePreviewZstdCompression () : void
2022-08-31 03:03:51 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupZstdCompressionBucket ();
2022-08-31 03:03:51 +00:00
$bucketId = $data [ 'bucketId' ];
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-31 03:04:11 +00:00
'fileId' => ID :: unique (),
2022-08-31 03:03:51 +00:00
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
$fileId = $file [ 'body' ][ '$id' ];
//get image preview
$file3 = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 100 ,
'borderRadius' => '50' ,
'opacity' => '0.5' ,
'output' => 'png' ,
'rotation' => '45' ,
]);
$this -> assertEquals ( 200 , $file3 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/png' , $file3 [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $file3 [ 'body' ]);
}
2026-02-05 22:54:14 +00:00
public function testUpdateBucketFile () : void
2021-06-20 11:20:35 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupBucketFile ();
2021-06-20 11:20:35 +00:00
/**
* Test for SUCCESS
*/
$file = $this -> client -> call ( Client :: METHOD_PUT , '/storage/buckets/' . $data [ 'bucketId' ] . '/files/' . $data [ 'fileId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2023-06-01 05:46:14 +00:00
'name' => 'logo_updated.png' ,
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-15 11:24:31 +00:00
Permission :: read ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: update ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: delete ( Role :: user ( $this -> getUser ()[ '$id' ])),
2022-08-03 04:17:49 +00:00
]
2021-06-20 11:20:35 +00:00
]);
$this -> assertEquals ( 200 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $file [ 'body' ][ '$id' ]);
2022-12-19 11:21:09 +00:00
$dateValidator = new DatetimeValidator ();
$this -> assertEquals ( true , $dateValidator -> isValid ( $file [ 'body' ][ '$createdAt' ]));
2023-06-01 05:46:14 +00:00
$this -> assertEquals ( 'logo_updated.png' , $file [ 'body' ][ 'name' ]);
2021-06-20 11:20:35 +00:00
$this -> assertEquals ( 'image/png' , $file [ 'body' ][ 'mimeType' ]);
$this -> assertEquals ( 47218 , $file [ 'body' ][ 'sizeOriginal' ]);
//$this->assertEquals(54944, $file['body']['sizeActual']);
//$this->assertEquals('gzip', $file['body']['algorithm']);
//$this->assertEquals('1', $file['body']['fileOpenSSLVersion']);
//$this->assertEquals('aes-128-gcm', $file['body']['fileOpenSSLCipher']);
//$this->assertNotEmpty($file['body']['fileOpenSSLTag']);
//$this->assertNotEmpty($file['body']['fileOpenSSLIV']);
2022-08-02 09:19:15 +00:00
$this -> assertIsArray ( $file [ 'body' ][ '$permissions' ]);
2022-08-13 14:10:28 +00:00
$this -> assertCount ( 3 , $file [ 'body' ][ '$permissions' ]);
2021-06-21 07:06:28 +00:00
2021-06-20 11:20:35 +00:00
/**
2021-06-21 06:58:06 +00:00
* Test for FAILURE unknown Bucket
2021-06-20 11:20:35 +00:00
*/
2021-06-21 06:58:06 +00:00
$file = $this -> client -> call ( Client :: METHOD_PUT , '/storage/buckets/empty/files/' . $data [ 'fileId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
2022-08-03 04:17:49 +00:00
'permissions' => [
2022-08-15 11:24:31 +00:00
Permission :: read ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: update ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: delete ( Role :: user ( $this -> getUser ()[ '$id' ])),
2022-08-03 04:17:49 +00:00
]
2021-06-21 06:58:06 +00:00
]);
2021-06-21 07:06:28 +00:00
2021-06-21 06:58:06 +00:00
$this -> assertEquals ( 404 , $file [ 'headers' ][ 'status-code' ]);
2021-06-20 11:20:35 +00:00
}
2026-02-05 22:54:14 +00:00
public function testFilePreview () : void
2025-10-30 21:58:02 +00:00
{
2026-02-05 22:54:14 +00:00
$data = $this -> setupBucketFile ();
2025-10-30 21:58:02 +00:00
$bucketId = $data [ 'bucketId' ];
2025-10-30 22:26:30 +00:00
$fileId = $data [ 'fileId' ];
2025-10-30 21:58:02 +00:00
// Preview PNG as webp
$preview = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'width' => 300 ,
'height' => 300 ,
'output' => 'webp' ,
]);
$this -> assertEquals ( 200 , $preview [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'image/webp' , $preview [ 'headers' ][ 'content-type' ]);
$this -> assertNotEmpty ( $preview [ 'body' ]);
}
2026-03-26 18:04:41 +00:00
public function testDeletePartiallyUploadedFile () : void
{
// Create a bucket for this test
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket Partial Upload' ,
'fileSecurity' => true ,
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$bucketId = $bucket [ 'body' ][ '$id' ];
// Simulate a partial (cancelled) chunked upload by sending only the first chunk
$source = __DIR__ . " /../../../resources/disk-a/large-file.mp4 " ;
$totalSize = \filesize ( $source );
$chunkSize = 5 * 1024 * 1024 ; // 5MB chunks
$mimeType = mime_content_type ( $source );
2026-03-26 18:34:19 +00:00
$handle = fopen ( $source , " rb " );
$this -> assertNotFalse ( $handle , " Could not open test resource: $source " );
$chunkData = fread ( $handle , $chunkSize );
fclose ( $handle );
2026-03-26 18:04:41 +00:00
$curlFile = new \CURLFile (
'data://' . $mimeType . ';base64,' . base64_encode ( $chunkData ),
$mimeType ,
'large-file.mp4'
);
// Send only the first chunk (bytes 0 to chunkSize-1 of totalSize)
$end = min ( $chunkSize - 1 , $totalSize - 1 );
$partialFile = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'content-range' => 'bytes 0-' . $end . '/' . $totalSize ,
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => $curlFile ,
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $partialFile [ 'headers' ][ 'status-code' ]);
$fileId = $partialFile [ 'body' ][ '$id' ];
// Confirm the file is in a pending state (chunksTotal > chunksUploaded)
$this -> assertGreaterThan (
$partialFile [ 'body' ][ 'chunksUploaded' ],
$partialFile [ 'body' ][ 'chunksTotal' ],
'File should be partially uploaded (pending)'
);
// Delete the partially-uploaded (pending) file — this should succeed
$deleteResponse = $this -> client -> call ( Client :: METHOD_DELETE , '/storage/buckets/' . $bucketId . '/files/' . $fileId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $deleteResponse [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $deleteResponse [ 'body' ]);
// Confirm the file is gone
$getResponse = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId . '/files/' . $fileId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $getResponse [ 'headers' ][ 'status-code' ]);
2026-03-26 18:34:19 +00:00
// Clean up the test bucket
$deleteBucketResponse = $this -> client -> call ( Client :: METHOD_DELETE , '/storage/buckets/' . $bucketId , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]);
$this -> assertEquals ( 204 , $deleteBucketResponse [ 'headers' ][ 'status-code' ]);
2026-03-26 18:04:41 +00:00
}
2026-02-05 22:54:14 +00:00
public function testDeleteBucketFile () : void
2021-06-20 11:20:35 +00:00
{
2026-02-05 22:54:14 +00:00
// Create a fresh file just for deletion testing (not using cache since we delete it)
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket Delete' ,
'fileSecurity' => true ,
'maximumFileSize' => 2000000 ,
'allowedFileExtensions' => [ 'jpg' , 'png' ],
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$bucketId = $bucket [ 'body' ][ '$id' ];
$file = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $file [ 'headers' ][ 'status-code' ]);
// First update the file (to test that delete works after update)
$file = $this -> client -> call ( Client :: METHOD_PUT , '/storage/buckets/' . $bucketId . '/files/' . $file [ 'body' ][ '$id' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'name' => 'logo_updated.png' ,
'permissions' => [
Permission :: read ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: update ( Role :: user ( $this -> getUser ()[ '$id' ])),
Permission :: delete ( Role :: user ( $this -> getUser ()[ '$id' ])),
]
]);
$this -> assertEquals ( 200 , $file [ 'headers' ][ 'status-code' ]);
$data = [ 'bucketId' => $bucketId , 'fileId' => $file [ 'body' ][ '$id' ]];
2021-06-20 11:20:35 +00:00
/**
* Test for SUCCESS
*/
$file = $this -> client -> call ( Client :: METHOD_DELETE , '/storage/buckets/' . $data [ 'bucketId' ] . '/files/' . $data [ 'fileId' ], array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $file [ 'body' ]);
2023-08-18 18:20:29 +00:00
$file = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $data [ 'bucketId' ] . '/files/' . $data [ 'fileId' ], array_merge ([
2021-06-20 11:20:35 +00:00
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 404 , $file [ 'headers' ][ 'status-code' ]);
}
2026-01-03 10:12:55 +00:00
public function testBucketTotalSize () : void
{
$bucket = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets' , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
], [
'bucketId' => ID :: unique (),
'name' => 'Test Bucket Size' ,
'permissions' => [
Permission :: read ( Role :: any ()),
Permission :: create ( Role :: any ()),
],
]);
$this -> assertEquals ( 201 , $bucket [ 'headers' ][ 'status-code' ]);
$bucketId = $bucket [ 'body' ][ '$id' ];
// bucket should have totalSize = 0 (no files)
$emptyBucket = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]);
$this -> assertEquals ( 200 , $emptyBucket [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'totalSize' , $emptyBucket [ 'body' ]);
$this -> assertEquals ( 0 , $emptyBucket [ 'body' ][ 'totalSize' ]);
// upload first file
$file1 = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/logo.png' ), 'image/png' , 'logo.png' ),
]);
$this -> assertEquals ( 201 , $file1 [ 'headers' ][ 'status-code' ]);
// upload second file
$file2 = $this -> client -> call ( Client :: METHOD_POST , '/storage/buckets/' . $bucketId . '/files' , array_merge ([
'content-type' => 'multipart/form-data' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'fileId' => ID :: unique (),
'file' => new CURLFile ( realpath ( __DIR__ . '/../../../resources/image.webp' ), 'image/webp' , 'image.webp' ),
]);
$this -> assertEquals ( 201 , $file2 [ 'headers' ][ 'status-code' ]);
2026-01-07 08:27:41 +00:00
$bucket = $this -> client -> call ( Client :: METHOD_GET , '/storage/buckets/' . $bucketId , [
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'x-appwrite-key' => $this -> getProject ()[ 'apiKey' ],
]);
2026-01-03 10:12:55 +00:00
2026-01-07 08:27:41 +00:00
$this -> assertEquals ( 200 , $bucket [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'totalSize' , $bucket [ 'body' ]);
$this -> assertIsInt ( $bucket [ 'body' ][ 'totalSize' ]);
2026-01-03 10:12:55 +00:00
2026-01-07 08:27:41 +00:00
/* will always be 0 in tests because the worker runs hourly! */
$this -> assertGreaterThanOrEqual ( 0 , $bucket [ 'body' ][ 'totalSize' ]);
2026-01-03 10:12:55 +00:00
}
2021-06-21 07:06:28 +00:00
}