Storing Files in S3 Buckets Using the AWS SDK and PHP

Camilo Herrera
winkhosting
Published in
17 min readFeb 15, 2023
Photo by Artem Maltsev on Unsplash

We all want to save files spending little money, your server wants to save files, your PC, your Docker container, your neighbor, and even your grandmother. We all want reliable, affordable, and cheap storage.

In my particular case, I did not want to pay for traditional storage to save backups, in the end backups are rarely used. It would not be money well invested and remember that in our days with IaaS, a miscalculation in the use of resources can leave you homeless.

Pro tip: Always look for a storage or IaaS provider with fixed and predictable prices. Yes, I’m talking to you Google Cloud, Microsoft Azure and Amazon AWS users, I don’t know how you sleep peacefully at night.

So, while walking my dog in the park drinking a coffee, (that’s when good ideas come up, walk more!), I wondered:

How will I store more than 10TB of backups that are accessible, easy to sync, download and restore… at a good price?

Well my dear reader, the answer is right there in front of you, it is called “Cold Storage” and its last name is S3.

When I received that answer that the cold morning breeze whispered to me, I ran home and left my dog in the park very sure that he would know how to return on his own, and if he did not succeed he was not worthy of being my pet.

I set out to investigate and this was the solution:

What We’re Going to Need

Let’s review the list of things we’re going to need before we start:

  • An S3 bucket obviously for testing
  • A library compatible with PHP to connect to a bucket
  • A development and testing environment for your scripts, your PC will suffice.
  • Hot coffee
  • Great music

The S3 Bucket

For our solution, any S3 bucket provider will do, as long as it sticks to the standard definition of the REST API designed by Amazon.

You can open an account on AWS that allows you to use free (for 12 months) up to 5GB S3 storage, you can also go to IDrive.com that allows you up to 10GB free or you can contact us and get an S3 storage plan with us at Winkhosting.co.

No matter which option you choose, follow the instructions to create a bucket and call it “testing”, “mybucket” or “B. McBucket,” whatever name you want.

Then go to the “Access Keys” option, in most providers it has the same name. There you may create one… “Access Key” to allow access to the bucket and perform read/write operations.

The information generated will look like this:

Region: us-west
Endpoint: my.bucketproviderendpoint.com
Access Key ID: ez4GrOLuSx9E5VlEI0ir
Secret Access Key: RMzyjCTR95VM8ilYIZuxf0VvOKoNh4209bIUuthN

Remember that you need these four parameters to establish the connection. (Region, Endpoint, Access Key ID, and Secret Access Key).

That’s it, with this data and our bucket ready we can move on.

The PHP library

Searching for the library was relatively easy. Amazon already provides a fairly complete PHP SDK.

Here you can download the .phar file you will find it at the installation section under the heading “Installing by using the packaged phar”. The file must be saved with the name “aws.phar” on your PC or server.

Implementation

Okay, let’s get to the interesting part of this matter. First some requirements to keep in mind:

  • We are using PHP 8.1.6
  • By default PHP includes support for .phar files, if you have any difficulty trying to use them you can check the documentation here
  • We will implement a component intended for console but with some tweaks it can be used on the web if you are brave.

We will start by creating our solution directory, I will call it “s3commander” because it sounds professional and gives it personality. You can call it whatever you want, you are an adult and you can already make your own decisions.

In our “s3commander” directory we will save the aws.phar file that we previously downloaded and create two files and two directories, the first file will be named “run.php”, (this will be our entry point to execute the actions of our component) and the second file will be “S3Commander.php”, (this will contain the class that we will use to implement the behavior and attributes of our component).

Regarding to the two directories, the first will be “myfiles”, the files in it will be uploaded to the bucket, the second directory will be called “mydownloadedfiles” and will be used, (as the name implies), to save the files downloaded from the bucket to our PC or Server.

The structure of files and directories will look like this:

/s3commander
/myfiles
/mydownloadedfiles
run.php
S3Commander.php
aws.phar

If you want to generate some test files to upload, you can use the following command in Windows using PowerShell inside the /myfiles directory:

for ($num=1 ; $num -le 130; $num++){ fsutil file createnew testfile_$num.txt 100000 }

Or on Linux:

for i in {1..130}; do dd if=/dev/urandom bs=1024 count=100 of=testfile_${i}.txt; done

130 files of 100K in size (each) will be created.

Now let’s explore the two main files, “S3Commander.php” and “run.php”.

S3Commander.php

Let’s start with this file including our phar library downloaded from Amazon.

<?php
require __DIR__ . '/aws.phar';

Remember that __DIR__ is a “magical” PHP constant (all PHP is magical, I do not understand why it should be said literally but that is how it is.). This constant returns the current execution directory of your script, this will help us to have control of the path once we use it within our component.

Once our phar file is included in “S3Commander.php”, we can proceed with the creation of our class.

We will start with the declaration of the class, the definition of the properties to be used and the constructor, like this:

Defining class, constructor, and attributes

<?php
//We include our library to connect to the bucket, thank you Amazon!.
require __DIR__ . '/aws.phar';

class S3Commander
{

//Amazon SDK Credentials Class Instance
private Aws\Credentials\Credentials $credentials;
//Bucket Access Key ID
private string $accessKeyID;
//Secret access Key associated with the access Key ID to authenticate the connection
private string $secretAccessKey;
//Amazon SDK S3Client Class Instance
private Aws\S3\S3Client $s3Client;
//Text string that will contain the region where the bucket is located
private string $region;
//Endpoint server URL
private string $endpointURL;
//Bucket name
private string $bucketName;
//Downloaded files save path
private string $downloadPath;
//SSL/TLS certificate validation Flag, use false while testing, true on production
private bool $httpSSLTLSVerify;

/**
* Here we define the default values for each of the attributes of the class,
* In this case we assign the text strings an empty value, verification of
* SSL/TLS active and the download directory "mydownloadedfiles" within the path
* where this file is located.
*/
function __construct()
{
$this->accessKeyID = "";
$this->secretAccessKey = "";
$this->region = "";
$this->endpointURL = "";
$this->bucketName = "";
$this->httpSSLTLSVerify = true;
$this->setDownloadPath(__DIR__ . "/mydownloadedfiles");
}

Next, we will define six functions to manage the bucket connection configuration.

Initialization and Configuration functions

    /**
* Receive an Accesss Key ID and Secret Access Key to create the
* AwsCredentialsCredentials object used by our SDK to authenticate
* The connection made.
* @param string $accesKeyID Access Key ID to be uses by the Credentials object
* @param string $secretAccessKey Secret key associated with the Access Key ID
* @return void
*/
public function setCredentials(string $accessKeyID, string $secretAccessKey): void
{
$this->accessKeyID = $accessKeyID;
$this->secretAccessKey = $secretAccessKey;
$this->credentials = new Aws\Credentials\Credentials($this->accessKeyID, $this->secretAccessKey);
}

/**
* Initializes an instance of S3Client (Defined in SDK) to perform operations
* in the bucket.
* @param string $region Text string indicating the geographic region where
* the bucket is located
* @param string $endpointURL URL of the server to which the client will connect.
* @param bool $httpSSLTLSVerify true/false value that indicates whether to validate
* the SSL/TLS certificate used by the client, to establish
* the test connection it is recommended to set the value false,
* on production env. true.
* @return void
*/
public function initClient(string $region, string $endpointURL, bool $httpSSLTLSVerify = true): void
{

$this->region = $region;
$this->endpointURL = $endpointURL;
$this->httpSSLTLSVerify = $httpSSLTLSVerify;

$this->s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => $this->region,
'credentials' => $this->credentials,
'endpoint' => $this->endpointURL,
'http' => [
'verify' => $this->httpSSLTLSVerify
]
]);
}

/**
* Setter, allows to modify the bucket name.
* @param string $bucketName String that contains the bucket name.
* @return void
*/
public function setBucket(string $bucketName): void
{
$this->bucketName = $bucketName;
}

/**
* Setter, allows to modify the downloaded files path.
* This function fixes the path if the script is used on Windows OS.
* @param string $downloadPath String that contains the local path to be used.
* @return void
*/
public function setDownloadPath(string $downloadPath): void
{
$this->downloadPath = $this->fixPathWindows($downloadPath);

if (!str_ends_with($this->downloadPath, "/")) {
$this->downloadPath .= "/";
}
}

/**
* This function shows on screen (console) the text sent in $messageText
* @param string $messageText Message to be shown
* @param bool $noDate Indicates whether you want to add the datetime and
* milliseconds at the beginning of the message to be
* displayed, by default false indicating that it is
* always added.
* @return void
*/
private function echoMessage(string $messageText, bool $noDate = false): void
{
$echotext = $messageText . PHP_EOL;

if (!$noDate) {
$echotext = "[" . date("Y-m-d H:i:s.u") . "] " . $echotext;
}

echo $echotext;
}

/**
* Helper, path normalization on Windows OS
* @param string $filePath Path to normalize
* @return string Normalized path.
*/
private function fixPathWindows(string $filePath): string
{
return str_replace("\\", "/", $filePath);
}

The comments in each function explain its purpose, I think it is not necessary to go into details. The important thing is these functions is that they allow us to:

  • Set authentication parameters (setCredentials)
  • Initialize our S3 client with endpoint URL, region and SSL/TLS certificate verification (initClient)
  • Set the bucket name (setBucket)
  • Set the save path for downloaded files (setDownloadPath)
  • Show messages on screen (echoMessage)
  • Adjust paths in Windows operating system to normalize directory separator (fixPathWindows).

Later we will see its use, now let’s see the actions that we can perform in the bucket, there will be four.

Funciones asociadas a acciones en un bucket

    /**
* This function uploads a file to the bucket.
* @param string $filePath Full path of the file to be uploaded.
* @return void
*/
public function putFile(string $filePath): void
{
$filePath = $this->fixPathWindows($filePath);

$fileName = basename($filePath);

try {

if (!file_exists($filePath)) {
throw new Exception("El archivo {$filePath} no existe");
}

$putRes = $this->s3Client->putObject([
'Bucket' => $this->bucketName,
'Key' => $fileName,
'Body' => fopen($filePath, 'r'),
'ACL' => 'private',
]);

$this->echoMessage("El archivo {$filePath} fue cargado al bucket {$this->bucketName}");
$this->echoMessage("URL del archivo: " . $putRes->get('ObjectURL'));
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Ocurrió un error al intentar cargar el archivo en la ruta {$filePath}" . PHP_EOL . $e->getMessage());
}
}

/**
* This function downloads an object(file) from the bucket.
* @param string $fileNameInBucket String that contains the filename (Key) to be downloaded
* @return void
*/
public function getFile(string $fileNameInBucket): void
{

try {

if (!file_exists($this->downloadPath)) {
throw new Exception("El directorio de descarga {$this->downloadPath} no existe");
}

$getRes = $this->s3Client->getObject([
'Bucket' => $this->bucketName,
'Key' => $fileNameInBucket,
'SaveAs' => $this->downloadPath . $fileNameInBucket,
]);

$this->echoMessage("El archivo {$fileNameInBucket} fue descargado y guardado en {$this->downloadPath}{$fileNameInBucket}");
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Ocurrió un error al intentar descargar el archivo {$fileNameInBucket} en la ruta {$this->downloadPath}" . PHP_EOL . $e->getMessage());
}
}

/**
* Delete a file(object) from the bucket.
* @param string $fileNameInBucket String that contains the name (key) of the object to be removed.
* @return void
*/
public function delFile(string $fileNameInBucket): void
{

try {

$putRes = $this->s3Client->deleteObject([
'Bucket' => $this->bucketName,
'Key' => $fileNameInBucket
]);

$this->echoMessage("El archivo {$fileNameInBucket} fue borrado del bucket {$this->bucketName}");
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Ocurrió un error al intentar borrar el archivo {$fileNameInBucket} en el bucket {$this->bucketName}" . PHP_EOL . $e->getMessage());
}
}

/**
* Creates a full list of the objects (files) in the bucket
* this list can be really long, use it with caution.
* @return void
*/
public function listAll(): void
{
$continuationToken = "";

do {

$config = [
"Bucket" => $this->bucketName,
"MaxKeys" => 50
];

if (!empty($continuationToken)) {
$config["ContinuationToken"] = $continuationToken;
}

$resultFiles = $this->s3Client->listObjectsV2($config);
$resultFiles = $resultFiles->toArray();

foreach ($resultFiles["Contents"] as $bucketObject) {
$this->echoMessage("Nombre: " . $bucketObject["Key"] . " Modificado: " . $bucketObject["LastModified"]->__toString());
}

if (!isset($resultFiles["IsTruncated"])) {
$resultFiles["IsTruncated"] = 0;
}

if ($resultFiles["IsTruncated"] == 1) {
$continuationToken = $resultFiles["NextContinuationToken"];
}
} while ($resultFiles["IsTruncated"] == 1);
}

As you can see, we can perform the following actions:

  • Upload files (putFile)
  • Download files (getFile)
  • Delete File (delFile)
  • List all files in the bucket (listAll), this last function should be used with caution, it can generate a fairly extensive screen output, but do not worry, the code at least has pagination of the downloaded results to avoid high memory consumption, (we are not vulgar programmers … well… not that much).

Now that we have the musical instruments, let’s see how they achieve harmony in the execution when they sound together. Our class will finally be as follows:

S3Commander Complete Class

<?php
//We include our library to connect to the bucket, thank you Amazon!.
require __DIR__ . '/aws.phar';

class S3Commander
{

//Amazon SDK Credentials Class Instance
private Aws\Credentials\Credentials $credentials;
//Bucket Access Key ID
private string $accessKeyID;
//Secret access Key associated with the access Key ID to authenticate the connection
private string $secretAccessKey;
//Amazon SDK S3Client Class Instance
private Aws\S3\S3Client $s3Client;
//Text string that will contain the region where the bucket is located
private string $region;
//Endpoint server URL
private string $endpointURL;
//Bucket name
private string $bucketName;
//Downloaded files save path
private string $downloadPath;
//SSL/TLS certificate validation Flag, use false while testing, true on production
private bool $httpSSLTLSVerify;

/**
* Here we define the default values for each of the attributes of the class,
* In this case we assign the text strings an empty value, verification of
* SSL/TLS active and the download directory "mydownloadedfiles" within the path
* where this file is located.
*/
function __construct()
{
$this->accessKeyID = "";
$this->secretAccessKey = "";
$this->region = "";
$this->endpointURL = "";
$this->bucketName = "";
$this->httpSSLTLSVerify = true;
$this->setDownloadPath(__DIR__ . "/mydownloadedfiles");
}

/**
* Receive an Accesss Key ID and Secret Access Key to create the
* AwsCredentialsCredentials object used by our SDK to authenticate
* The connection made.
* @param string $accesKeyID Access Key ID to be uses by the Credentials object
* @param string $secretAccessKey Secret key associated with the Access Key ID
* @return void
*/
public function setCredentials(string $accessKeyID, string $secretAccessKey): void
{
$this->accessKeyID = $accessKeyID;
$this->secretAccessKey = $secretAccessKey;
$this->credentials = new Aws\Credentials\Credentials($this->accessKeyID, $this->secretAccessKey);
}

/**
* Initializes an instance of S3Client (Defined in SDK) to perform operations
* in the bucket.
* @param string $region Text string indicating the geographic region where
* the bucket is located
* @param string $endpointURL URL of the server to which the client will connect.
* @param bool $httpSSLTLSVerify true/false value that indicates whether to validate
* the SSL/TLS certificate used by the client, to establish
* the test connection it is recommended to set the value false,
* on production env. true.
* @return void
*/
public function initClient(string $region, string $endpointURL, bool $httpSSLTLSVerify = true): void
{

$this->region = $region;
$this->endpointURL = $endpointURL;
$this->httpSSLTLSVerify = $httpSSLTLSVerify;

$this->s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => $this->region,
'credentials' => $this->credentials,
'endpoint' => $this->endpointURL,
'http' => [
'verify' => $this->httpSSLTLSVerify
]
]);
}

/**
* Setter, allows to modify the bucket name.
* @param string $bucketName String that contains the bucket name.
* @return void
*/
public function setBucket(string $bucketName): void
{
$this->bucketName = $bucketName;
}

/**
* Setter, allows to modify the downloaded files path.
* This function fixes the path if the script is used on Windows OS.
* @param string $downloadPath String that contains the local path to be used.
* @return void
*/
public function setDownloadPath(string $downloadPath): void
{
$this->downloadPath = $this->fixPathWindows($downloadPath);

if (!str_ends_with($this->downloadPath, "/")) {
$this->downloadPath .= "/";
}
}

/**
* This function uploads a file to the bucket.
* @param string $filePath Full path of the file to be uploaded.
* @return void
*/
public function putFile(string $filePath): void
{
$filePath = $this->fixPathWindows($filePath);

$fileName = basename($filePath);

try {

if (!file_exists($filePath)) {
throw new Exception("The file {$filePath} does not exists.");
}

$putRes = $this->s3Client->putObject([
'Bucket' => $this->bucketName,
'Key' => $fileName,
'Body' => fopen($filePath, 'r'),
'ACL' => 'private',
]);

$this->echoMessage("The file {$filePath} was uploaded to the bucket {$this->bucketName}");
$this->echoMessage("Object URL: " . $putRes->get('ObjectURL'));
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Error trying to upload the file in {$filePath}" . PHP_EOL . $e->getMessage());
}
}

/**
* This function downloads an object(file) from the bucket.
* @param string $fileNameInBucket String that contains the filename (Key) to be downloaded
* @return void
*/
public function getFile(string $fileNameInBucket): void
{

try {

if (!file_exists($this->downloadPath)) {
throw new Exception("The download path {$this->downloadPath} does not exists.");
}

$getRes = $this->s3Client->getObject([
'Bucket' => $this->bucketName,
'Key' => $fileNameInBucket,
'SaveAs' => $this->downloadPath . $fileNameInBucket,
]);

$this->echoMessage("The file {$fileNameInBucket} was downloaded to {$this->downloadPath}{$fileNameInBucket}");
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Error trying to download the file {$fileNameInBucket} to {$this->downloadPath}" . PHP_EOL . $e->getMessage());
}
}

/**
* Delete a file(object) from the bucket.
* @param string $fileNameInBucket String that contains the name (key) of the object to be removed.
* @return void
*/
public function delFile(string $fileNameInBucket): void
{

try {

$putRes = $this->s3Client->deleteObject([
'Bucket' => $this->bucketName,
'Key' => $fileNameInBucket
]);

$this->echoMessage("The file {$fileNameInBucket} was deleted from bucket {$this->bucketName}");
} catch (Aws\S3\Exception\S3Exception | Exception $e) {
$this->echoMessage("Error trying to delete the file {$fileNameInBucket} frombucket {$this->bucketName}" . PHP_EOL . $e->getMessage());
}
}

/**
* Creates a full list of the objects (files) in the bucket
* this list can be really long, use it with caution.
* @return void
*/
public function listAll(): void
{
$continuationToken = "";

do {

$config = [
"Bucket" => $this->bucketName,
"MaxKeys" => 50
];

if (!empty($continuationToken)) {
$config["ContinuationToken"] = $continuationToken;
}

$resultFiles = $this->s3Client->listObjectsV2($config);
$resultFiles = $resultFiles->toArray();

foreach ($resultFiles["Contents"] as $bucketObject) {
$this->echoMessage("Name: " . $bucketObject["Key"] . " Modified: " . $bucketObject["LastModified"]->__toString());
}

if (!isset($resultFiles["IsTruncated"])) {
$resultFiles["IsTruncated"] = 0;
}

if ($resultFiles["IsTruncated"] == 1) {
$continuationToken = $resultFiles["NextContinuationToken"];
}
} while ($resultFiles["IsTruncated"] == 1);
}

/**
* This function shows on screen (console) the text sent in $messageText
* @param string $messageText Message to be shown
* @param bool $noDate Indicates whether you want to add the datetime and
* milliseconds at the beginning of the message to be
* displayed, by default false indicating that it is
* always added.
* @return void
*/
private function echoMessage(string $messageText, bool $noDate = false): void
{
$echotext = $messageText . PHP_EOL;

if (!$noDate) {
$echotext = "[" . date("Y-m-d H:i:s.u") . "] " . $echotext;
}

echo $echotext;
}

/**
* Helper, path normalization on Windows OS
* @param string $filePath Path to normalize
* @return string Normalized path.
*/
private function fixPathWindows(string $filePath): string
{
return str_replace("\\", "/", $filePath);
}
}

Let’s continue with “run.php

Run.php

We will use this file to test the functions created in our component and it will look like this:

<?php
//Include our S3Commander class.
require __DIR__ . '/S3Commander.php';

/**
* In this section we initialize some constants needed for testing,
* these are the values that you should modify to reflect the environment
* and access data to the bucket that you are going to use.
*
* $_FILES_DIR is the local path where the files to be uploaded are stored
* $_ACCESS_KEY_ID Bucket Access ID
* $_SECRET_ACCESS_KEY The secret key associated with the ID to authenticate the connection
* $_REGION The region where the bucket is located, this information is provided by
* the service provider when creating it.
* $_BUCKET Bucket Name
* $_ENDPOINT URL to connect to the server where the bucket is located
* $_DOWNLOAD_DIR Path where files that are downloaded from the bucket will be saved.
*/
$_FILES_DIR = str_replace("\\", "/", __DIR__) . "/myfiles";
$_ACCESS_KEY_ID = "rl0z4GeOuE5V9riLSEIx";
$_SECRET_ACCESS_KEY = "bIUilY4209uthVMIZNRMzy5uoNh8xf0VvOK9jCTR";
$_REGION = "Oregon";
$_BUCKET = "testing";
$_ENDPOINT = "https://my.endpointurl.com";
$_DOWNLOAD_DIR = str_replace("\\", "/", __DIR__) . "/mydownloadedfiles";

//Let's create our S3Commander object.
$s3Comm = new S3Commander();

//Set the access credentials.
$s3Comm->setCredentials($_ACCESS_KEY_ID, $_SECRET_ACCESS_KEY);

/**
* We set the endpoint region and URL, also a parameter is included to set if the
* SSL/TLS certificate used is validated locally, for practical and testing
* purposes we do not validate this but in production it must be done
* for security purposes.
*/
$s3Comm->initClient($_REGION, $_ENDPOINT, false);

//Set the bucket name to be used
$s3Comm->setBucket($_BUCKET);

//Set the downlad path.
$s3Comm->setDownloadPath($_DOWNLOAD_DIR);

/**
* For this test we are going to generate a simple list of the files in the
* predefined directory /myfiles, if you need to load a more elaborated
* directory structure you will need to change the putFile function in the class.
*/
$arrUploadFiles = array_diff(
scandir($_FILES_DIR),
array('..', '.')
);

foreach ($arrUploadFiles as $key => $fileName) {
//Upload each file in the directory
$s3Comm->putFile($_FILES_DIR . "/" . $fileName);
}

//List the objects in the bucket
$s3Comm->listAll();

//Download a file(object)
$s3Comm->getFile("testfile_1.txt");

//Delete test.
$s3Comm->delFile("testfile_1.txt");

//The End.

The first thing we do in our file is to include our definition of the S3Commander class and then initialize some values required to configure the S3 client:

  • $_FILES_DIR It is the path of the directory where the files to be uploaded.
  • $_ACCESS_KEY_ID It is the access identifier to the bucket that was generated in the provider and will allow us to connect to it.
  • $_SECRET_ACCESS_KEY This is the secret key associated with the Access Key ID to authenticate the connection to the bucket.
  • $_REGION It will indicate the region where the bucket is located, this information is delivered by the service provider when the bucket is created.
  • $_BUCKET This variable contains the name of the bucket to which we will connect.
  • $_ENDPOINT Contains the URL of the server where the bucket is located, usually starts with https://
  • $_DOWNLOAD_DIR It is the directory where the files that are downloaded from the bucket will be saved. It must exist and be a directory that the script has access to.

To continue we will instantiate the S3Commander class, set the access credentials (setCredentials), initialize the client with the data of the server that contains our bucket (initClient), select the bucket (setBucket) and set the download directory (setDownloadPath).

Then we will proceed with reading the filenames in the “myfiles” directory and load them into the $arrUploadFiles array to perform the upload test.

Next, we will loop through the array and load each of files using the “putFile” function of our $s3Comm object, the result of the upload will be displayed in the console.

When the file upload is complete, we will use the “listAll” function to query the bucket and generate the list of files with their last modified date (when they were uploaded) and display them in the console.

Finally, we will perform a test by downloading one of the files in the bucket with the name “testfile_1.txt”, if everything goes as expected, the file will be saved in “mydownloadedfiles” and the message of the result will be displayed in the console. Then, we will delete the file with the same name in the bucket (the copy in our local directory will be kept).

Running our script

To perform the test, set the configuration values in the variables within “run.php”, when they are ready verify that you have files to load in “myfiles”, start a command console, enter the “s3commander” directory and run the script like this:

>php run.php

I’m assuming php is a command that you have preconfigured to execute in any directory, i.e. it’s global, otherwise you’d have to use the full path of the executable in the command for it to work.

If all goes well, the result shown will be something like this:

#Uploaded files sample:
[2023-02-09 18:20:23.000000] The file /s3commander/myfiles/testfile_1.txt uploaded to the bucket testing
[2023-02-09 18:20:23.000000] Object URL: https://my.endpoint.com/testfile_1.txt
#Object list sample:
[2023-02-09 18:20:47.000000] Name: testfile_1.txt Modified: 2023-02-09T18:20:20+00:00
[2023-02-09 18:20:47.000000] Name: testfile_10.txt Modified: 2023-02-09T18:20:21+00:00
#Downloaded object sample:
[2023-02-09 18:20:48.000000] The file testfile_1.txt was downloaded to /s3commander/mydownloadedfiles/testfile_1.txt
#Deleteded object sample:
[2023-02-09 18:20:48.000000] The file testfile_1.txt was deleted from the bucket testing

And that’s it. You can now implement this type of storage to move your backups and store them safely, do not forget to regularly test your backup files and drink plenty of water.

And if you keep thinking about what happened to my dog, that’s fine, I attach a graphic test doing his thing:

And remember that in Winkhosting.co we are much more than hosting!.

--

--