Amazon S3 dengan CakePHP

Beberapa hari ini saya cukup disibukkan dengan memahami cara kerja Amazon Simple Storage Service (Amazon S3), yang merupakan salah satu layanan dari Amazon Web Service (AWS), dilanjutkan dengan menulis beberapa baris kode agar bisa bekerja dengan CakePHP . Ini adalah salah satu bagian dari situs yang sedang saya kerjakan.

Langsung aja. Library PHP5 untuk mengakses layanan Amazon S3 ini saya gunakan Class S3 dari http://undesigned.org.za/2007/10/22/amazon-s3-php-class, hasil karya dari Donovan Schönknecht.

Agar bisa diakses dalam CakePHP, file class S3 tadi (S3.php) diletakkan di folder app/vendor/. Setelah itu saya buat fungsi baru di dalam controller yang mengakses Amazon S3 nantinya.

function _initAws()
{
// AWS access info
if (!defined('awsAccessKey')) define('awsAccessKey', 'AKHTZQYAXRXHTZQYAUUM'); // Sesuaikan dengan AccessKey anda
if (!defined('awsSecretKey')) define('awsSecretKey', 'VJFcyIksmdnk90kngio'); // Sesuaikan dengan SecretKey anda

App::import('Vendor', 'S3', array('file'=>'S3.php'));
$s3 = new S3(awsAccessKey, awsSecretKey);
return $s3;
}

Kemudian jika di dalam salah satu fungsi controller anda (di dalam controller yang sama), anda ingin mengakses S3, cukup gunakan baris berikut :

$s3 = $this->_initAws();

$s3->putBucket('cdn.labanux.com', S3::ACL_PRIVATE); // Membuat bucket baru

$s3->putObjectFile($file_path, 'cdn.labanux.com', 'image/'.$file_name.'.xcf', S3::ACL_PRIVATE);

// Menyimpan ke bucket cdn.labanux.com, dengan nama file image/$filename.xcf (image itu hanyalah virtual folder, karena Amazon S3 tidak mensupport folder. Dengan dinamai seperti itu, maka file anda kelihatan seperti berada di dalam sebuah folder / subfolder

Oh iya, bucket itu unik, ndak ada yang sama di AWS. Terus asyiknya gini, kalau bucket kita bernama : labanux, maka bucketnya beralamat di s3.amazonaws.com/labanux, ataupun labanux.s3.amazonaws.com. Kalo nama bucketnya cdn-ku.org, maka bisa diakses di cdn-ku.org.s3.amazonaws.com, ataupun s3.amazonaws.com/cdn-ku.org

Nah kalo kita punya domain labanux.com, kita bisa nambahin subdomain cdn.labanux.com kan? Nah, di S3 nya kita bikin bucket dengan nama cdn.labanux.com. Jadi ntar bisa diakses dengan alamat cdn.labanux.com.s3.amazonaws.com.

Lalu gimana biar CDN (Content Delivery Network) nya beralamat di cdn.labanux.com? Gampang, di NS servernya dibuat record CNAME cdn.labanux.com diarahkan ke cdn.labanux.com.s3.amazonaws.com

Lalu bagaimana jika kita ingin mengakses file dari AWS untuk di berikan kepada user (di download user) ?

Kalau file & bucketnya public, bisa langsung diakses secara direct (misal filenya : image/fotoku.jpg) : s3.amazonaws.com/bucket/image/fotoku.jpg. Atau kalau mengikuti contoh di atas jadinya : cdn.labanux.com.s3.amazonaws.com/image/fotoku.jpg, atau (ini yang saya pakai) : cdn.labanux.com/image/fotoku.jpg.

Nah, kalau file / bucketnya private. Ada dua cara. Cara pertama :

1. Ini langsung di dalam salah satu fungsi di controller.

$s3 = $this->_initAws();

// We'll be outputting an image
header('Content-type: image/jpeg');

header('Content-Transfer-Encoding: binary');
header('Expires: 0');


// Nama file : $image_name.jpg
header('Content-Disposition: attachment; filename="'.$image_name.'.jpg"');

// Mengambil file dari AWS
$file = $s3->getObject('cdn.labanux.com', 'image/'.$image_file);
echo $file->body;
exit();

Dengan cara tersebut, file dijemput dulu dari AWS ke webserver, baru dari webserver “diserahkan” ke user. Kekurangannya, tiap ada request download, webserver mengambil dulu filenya dari AWS, baru “diserahkan” ke user, yang berarti bandwith di webserver ikut terpakai.

2. Cara kedua adalah dengan memberikan temporary akses langsung ke servernya. :

$s3 = $this->_initAws();


$download_link = $s3->getAuthenticatedURL('cdn.labanux.com', 'image/fotoku.jpg', 250, true);
// <– ini hasilnya berupa link download ke file tersebut di AWS.

$this->set('download_link', $download_link);

Kemudian di file view nya :

echo $html->link('Download !', $download_link);


$download_link itu akan berbentuk seperti ini :

http://cdn.labanux.com/image/fotoku.jpg?AWSAccessKeyId=AKHTZQYAXRXHTZQYAUUM&Expires=1243281781&Signature=Ir7HrV65qCp0GHq%2BbqB5fUslNjs%3D

Kekurangannya? Semua orang bisa mengakses link download tersebut. Tenang.., link tersebut hanya valid untuk 250 detik *lihat parameter 250 pada fungsi di atas*. Jadi setelah 250 detik link itu tidak akan bisa diakses lagi.

Lalu gimana kalau downloadnya butuh waktu 400 detik? Jangan takut, kalau proses download sudah berjalan, dia akan tetap valid sampai download selesai.

Saya cuma ingin menyampaikan bagaimana ide Amazon S3 bisa bekerja dengan CakePHP. Tidak menutup kemungkinan dalam contoh saya ini ada kesalahan. Silahkan dicoba..

6 Comments

  • At 2009.05.27 13:27, Charly Silaban said:
    • At 2009.05.27 21:29, xebiet said:

      mantab, tapi mumet.
      bisa private g 😕

      • At 2009.06.15 22:05, Natali Ardianto said:

        Pak, kira-kira efektifkah biayanya pak? Saya sudah pakai kalkulatornya tapi ya terlalu banyak asumsi. Apakah bapak punya pengalaman tentang cost di S3?

        • At 2009.06.15 23:12, Okto Silaban said:

          Kalo untuk baru mulai sih, sepertinya memang murah.. Soalnya kita bisa punya server data dengan dana sangat – sangat minimal.. Kecuali kalo sudah gede.., mungkin pindah ke server sendiri. Tapi itu juga costnya kan gak murah.

          Cost yg paling mahal *menurut* kami adalah menemukan orang yg bener2 tahu apa yg dia kerjakan.. Dan orang yg beneran ngerti ini, rate nya juga tinggi kan.. 😛

          Btw, Mas ini foundernya Urbanesia.com yah? *sempet liat iklan lowongannya di milis id-php.

          Dah launching Urbanesia nya mas? *keknya beberapa link belum aktif..

          • At 2009.10.28 11:36, Natali Ardianto said:

            Belum launch pak 🙂 Masih masak-masak.

            • At 2011.05.27 16:52, restoran india said:

              secara keseluruhan keren cie tapi pasti rumit

              (Required)
              (Required, will not be published)

              apel