Amazon S3 Buckets mit PHP verwenden

Wer auf ein Amazon S3 mit PHP zugreifen muss, stößt für europäische Buckets unter Umständen auf Probleme. Hier habe ich die Lösung für Sie kostenlos!

Diese hier vorgestellte Klasse basiert auf der von Amazon bereitgestellten S3-Klasse, sie ist jedoch so umgeschrieben, dass sie auch auf europäische S3-Buckets zugreifen kann, was die veraltete Amazon-Klasse bezeichnender Weise nicht kann. (Stand: 2008) Diese Klasse beschränkt sich weiterhin auf die normalerweise benötigten Aktionen, so können zum Beispiel keine neuen Buckets angelegt werden.

s3.php
<?php
 
/*
 * ##################################################
 * #                                                #
 * # S3 Access Class                                #
 * # Accessing S3 buckets with PHP                  #
 * #                                                #
 * # Copyright (C) by René Knipschild               #
 * #                                                #
 * #                                email@rkcsd.com #
 * #               www.customsoftwaredevelopment.de #
 * #                                                #
 * ##################################################
 *
 * File: s3.php
 * Version: 1.0.0
 * Last modified: 2008/05/23 14:30 CEST
 * Author: René Knipschild
 *
 * ===Notes==========================================
 * Diese Klasse basiert auf der von Amazon bereit-
 * gestellten S3-Klasse, sie ist jedoch so umge-
 * schrieben, dass sie auch auf europäische S3-
 * Buckets zugreifen kann, was die veraltete Amazon-
 * Klasse bezeichnender Weise nicht kann. Diese
 * Klasse beschränkt sich weiterhin auf die normal-
 * erweise benötigten Aktionen, so können zum Bei-
 * spiel keine neuen Buckets angelegt werden.
 * ==================================================
 */
 
class s3
{
	var $S3_URL = "";
	var $verbs = array("GET"=>1, "DELETE"=>1, "PUT"=>1);
	var $_debug = false;
	var $keyId = "";
	var $secretKey = "";
	var $_verb = "GET";
	var $_acl = "public-read";
	var $_contentType = "application/octet-stream";
	var $_responseContentType = "text/xml";
	var $prefix = "";
	var $marker = "";
	var $max_keys = "";
	var $delimiter = "";
	var $bucketname = "";
 
	function s3($options = NULL)
	{
		define('GMT_DATE_RFC822', 'D, d M Y H:i:s T');
		$this->httpDate = gmdate(GMT_DATE_RFC822);
 
		$available_options = array("acl", "contentType");
		if (is_array($options)) {
			foreach ($options as $key => $value) {
				$this->debug_text("Option: $key");
				if (in_array($key, $available_options) ) {
					$this->debug_text("Valid Config options: $key");
					$property = '_'.$key;
					$this->$property = $value;
					$this->debug_text("Setting $property to $value");
				} else {
					$this->debug_text("ERROR: Config option: $key is not a valid option");
				}
			}
		}
 
		require_once('Crypt/HMAC.php');
		//$this->hasher =& new Crypt_HMAC($this->secretKey, "sha1");
		$this->hasher =& new Crypt_HMAC(STORAGE_SECRET_ACCESS_KEY, "sha1");
		require_once('HTTP/Request.php');
	}
 
	function sendRequest($resource, $verb = NULL, $objectdata = NULL, $acl = NULL, $contentType = NULL, $metadata = NULL)
	{
		if ($verb == NULL) {
			$verb = $this->verb;
		}
 
		if ($acl == NULL) {
			$aclstring = "";
		} else {
			$aclstring = "x-amz-acl:$acl\n";
		}
 
		$contenttypestring = "";		
		if ($contentType != NULL && ($verb == "PUT") && ($objectdata != NULL) && ($objectdata != "")) {
			$contenttypestring = "$contentType";
		}
 
		$this->httpDate = gmdate(GMT_DATE_RFC822);		
		$httpDate = $this->httpDate;
 
		$paramstring = "";
		$delim = "?";
 
		if (strlen($this->prefix)) {
			$paramstring .= $delim."prefix=".urlencode($this->prefix);
			$delim = "&";
		}
 
		if (strlen($this->marker)) {
			$paramstring .= $delim."marker=".urlencode($this->marker);
			$delim = "&";
		}
 
		if (strlen($this->max_keys)) {
			$paramstring .= $delim."max-keys=".$this->max_keys;
			$delim = "&";
		}
 
		if (strlen($this->delimiter)) {
			$paramstring .= $delim."delimiter=".urlencode($this->delimiter);
			$delim = "&";
		}
 
		$this->debug_text("HTTP Request sent to: " . $this->S3_URL . $resource . $paramstring);
 
		$req =& new HTTP_Request($this->S3_URL . $resource . $paramstring);
		$req->setMethod($verb);
 
		if (($objectdata != NULL) && ($objectdata != "")) {
			$contentMd5 = $this->hex2b64(md5($objectdata));
			$req->addHeader("CONTENT-MD5", $contentMd5);
			$this->debug_text("MD5 HASH OF DATA: " . $contentMd5);
			$contentmd5string = $contentMd5;
		} else {
			$contentmd5string = "";
		}
 
		if (strlen($contenttypestring)) {
			$this->debug_text("Setting content type to $contentType");
			$req->addHeader("CONTENT-TYPE", $contentType);
		}
 
		$req->addHeader("DATE", $httpDate);
 
		if (strlen($aclstring)) {
			$this->debug_text("Setting acl string to $acl");
			$req->addHeader("x-amz-acl", $acl);
		}
 
		$metadatastring = "";
		if (is_array($metadata)) {
			ksort($metadata);
			$this->debug_text("Metadata found.");
			foreach ($metadata as $key => $value) {
				$metadatastring .= "x-amz-meta-".$key.":".trim($value)."\n";
				$req->addHeader("x-amz-meta-".$key, trim($value));
				$this->debug_text("Setting x-amz-meta-$key to '$value'");
			}
		}
 
		if (($objectdata != NULL) && ($objectdata != "")) {
			$req->setBody($objectdata);
		}
 
		$stringToSign = "$verb\n$contentmd5string\n$contenttypestring\n$httpDate\n$aclstring$metadatastring/$this->bucketname/$resource";
		$this->debug_text("Signing String: $stringToSign");
		$signature = $this->hex2b64($this->hasher->hash($stringToSign));
		$req->addHeader("Authorization", "AWS " . $this->keyId . ":" . $signature);
 
		$req->sendRequest();		
 
		$this->_responseContentType = $req->getResponseHeader("content-type");
 
		if (strlen($req->getResponseBody())) {
			$this->debug_text($req->getResponseBody());
			return $req->getResponseBody();
		} else {
			$this->debug_text($req->getResponseHeader());
			return $req->getResponseHeader();
		}
	}
 
	function putObject($objectname, $objectdata, $bucketname = NULL, $acl = NULL, $contentType = NULL, $metadata = NULL)
	{
		if ($bucketname == NULL) {
			$bucketname = $this->bucketname;
		}
 
		if ($acl == NULL || $acl == "") {
			$acl = $this->_acl;
		}
 
		if ($contentType == NULL || $contentType == "") {
			$contentType = $this->_contentType;
		}
 
		if ($objectdata != NULL) {
			return $this->sendRequest($objectname, "PUT", $objectdata, $acl, $contentType, $metadata);
		} else {
			return false;
		}		
	}
 
	function deleteObject($objectname, $bucketname = NULL)
	{
		if ($bucketname == NULL) {
			$bucketname = $this->bucketname;
		}
		return $this->sendRequest($objectname, "DELETE");
	}
 
	function hex2b64($str)
	{
		$raw = '';
		for ($i=0; $i < strlen($str); $i+=2) {
			$raw .= chr(hexdec(substr($str, $i, 2)));
		}
		return base64_encode($raw);
	}
 
	function debug_text($text)
	{
		if ($this->_debug) {
			echo("<br>\n");
			print_r($text);
			echo("<br><br>\n\n");
		}
		return true;
	}
}
 
?>
dev/php/s3.txt · Zuletzt geändert: 23.10.2013, 23:47 Uhr von wikiredaktion@reneknipschild.de
 
Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht: CC Attribution-Share Alike 3.0 Unported
rkWiki wird freundlich bereitgestellt von
René Knipschild – Custom Software Development, Ihr Partner in Sachen IT-Beratung & individueller Software-Entwicklung. www.IT-Beratung-Nordhessen.de – Made in Germany
Copyleft inverted copyright sign 2012-2024 René Knipschild | www.reneknipschild.net | Impressum | Datenschutz