Wanzul Blog

Nota, pendapat, dan pengajaran yang aku bayar sendiri.

Object storage

Upload dan Download Fail S3 Guna PHP Biasa (Tak Perlu SDK)

Aku biasa dengan cloud storage macam Google Drive dan Microsoft OneDrive. Tapi dalam web development, provider macam ni tak berapa sesuai — sebab dia tak bagi link direct dan kekal ke fail yang kau upload. Untuk selesaikan masalah tu, object storage jadi pilihan yang senang dan boleh dipercayai.

Dalam OneDrive, link yang diberi bawa ke web interface, bukan ke fail asal. Kita perlukan hotlinking untuk guna fail dengan berkesan di web.

Dalam artikel ni, aku guna Object Storage daripada IPServerOne, bukan Amazon S3. Prosesnya hampir sama; kau cuma perlu tukar variable $s3_endpoint ikut provider kau.

Protip: Kalau kau tak biasa dengan PHP, kau boleh minta ChatGPT/Copilot reverse-engineer kod PHP ni jadi command cURL.


Upload ke S3

Untuk upload fail ke object storage, kau cuma perlu bagi parameter yang betul dan execute request cURL. Sebenarnya simple je — lebih kurang macam buat API call REST biasa.

Logik utama: Teras logik upload guna curl_init untuk buka connection ke endpoint S3, lepas tu CURLOPT_PUT untuk stream kandungan fail terus. Cara ni sangat efisien sebab ia elak overhead library pihak ketiga yang besar.

<?php

$file_to_upload = 'yourimage.png';
$bucket = 'wordpressha';
$s3_endpoint = 'ap-southeast-mys1.oss.ips1cloud.com';
$access_key = '5IRK7V7TVSV0B829WHAD';
$secret_key = 'I7BLtOZAsHdCDHMeyJ73QipBIPjLDCvWhIAzfynV';

$content_type = 'application/octet-stream';
$date_value = gmdate('D, d M Y H:i:s T');

$string_to_sign = "PUT\n\n{$content_type}\n{$date_value}\n/{$bucket}/{$file_to_upload}";
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, true));

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://{$bucket}.{$s3_endpoint}/{$file_to_upload}");
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, fopen($file_to_upload, 'r'));
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file_to_upload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  "Host: {$bucket}.{$s3_endpoint}",
  "Date: {$date_value}",
  "Content-Type: {$content_type}",
  "Authorization: AWS {$access_key}:{$signature}"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http_code == 200) {
  echo "File uploaded successfully.";
} else {
  echo "Failed to upload file. HTTP Status Code: {$http_code}";
}

Demo 💻

Demo ni tunjuk macam mana fail di-upload terus ke Object Storage:

Simple dan terus. Kau tak perlu import library berat semata-mata nak upload fail ke S3.

Akses fail dalam private bucket (download dari S3)

Objek (fail) dalam public bucket boleh diakses terus melalui URL dia. Tapi untuk private bucket, URL tu perlukan parameter authentication tambahan dalam query string untuk bagi akses.

Logik utama: Jana Presigned URL dibuat dengan hash masa expire dan path bucket guna hash_hmac dengan Secret Key kau. Sebab ni kiraan client-side, tak ada API call diperlukan untuk langkah ni — jadi ia sangat laju.

<?php

$object_key = 'yourimage.png';
$bucket = 'wordpressha';
$s3_endpoint = 'ap-southeast-mys1.oss.ips1cloud.com';
$access_key = '5IRK7V7TVSV0B829WHAD';
$secret_key = 'I7BLtOZAsHdCDHMeyJ73QipBIPjLDCvWhIAzfynV';

$expires = time() + 3600;
$method = 'GET';

$string_to_sign = "{$method}\n\n\n{$expires}\n/{$bucket}/{$object_key}";
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, true));

$presigned_url = "https://{$bucket}.{$s3_endpoint}/{$object_key}?AWSAccessKeyId={$access_key}&Expires={$expires}&Signature=" . urlencode($signature);

echo "Presigned URL: {$presigned_url}\n";

Contoh akses objek dalam Public Bucket

https://ap-southeast-mys1.oss.ips1cloud.com/wordpressha/test.jpg

Contoh akses objek dalam Private Bucket

https://wordpressha.ap-southeast-mys1.oss.ips1cloud.com/test.jpg?AWSAccessKeyId=KL6FSI64D6FEBHY77621&Expires=1734687785&Signature=4zRuNtWz%2F9ewHT%2FUF7c2mCfOxco%3D

Perhatikan parameter AWSAccessKeyId, Expires, dan Signature yang ditambah pada URL. Ni yang dipanggil Presigned URL.

Tengok balik kod tu, kau akan perasan penjanaan Presigned URL tak melibatkan API call. Ia dikira sepenuhnya daripada hash yang dijana daripada string yang di-salt dengan Secret Key kau.

Demo 💻

Demo ni tunjuk macam mana fail dalam private bucket boleh diakses:


Jangan susah hati nak cuba akses test bucket tu — akses dah dibatalkan. Contoh ni dibuat semata-mata untuk artikel ni 😉

Sekarang kau patut dah faham betul macam mana Object Storage berfungsi, dan macam mana nak integrate dengan PHP biasa! 😇

Wan Zulkarnain Avatar

Written by 


Comments

Leave a Reply