Статьи

Программирование Amazon S3, часть II

В первой части этой серии статей Джефф показал нам, как начать программировать сервис хранения S3 в Amazon. Если вы следовали этому руководству, вы настроили свою учетную запись AWS, загрузили библиотеку CloudFusion и настроили ее с помощью ключей аутентификации. Вы также видели несколько простых способов создания блоков и получения списков блоков из вашего PHP-кода.

На этой неделе мы пойдем дальше: покажем, как загружать файлы в S3, создавать простой сервис хранения миниатюр и распространять свои файлы с помощью CloudFront CDN.

Обе эти статьи были взяты из последнего выпуска книги SitePoint, «Разместите ваш веб-сайт в облаке», «Amazon Web Services Made Easy» . Они оба были взяты из главы 4, которая также доступна как часть бесплатного образца книги в формате PDF .

Я предполагаю, что вы уже проработали первую часть . Теперь, когда вы знаете, как создавать сегменты и перечислять их на веб-странице, пришло время поговорить об основной функции Amazon S3: хранении файлов. Но прежде чем мы это сделаем, пришло время сделать небольшой обход.

важно: выполнение кода

Программы в этой статье, начинающиеся с символа shebang ( #!/usr/bin/php ), должны запускаться из командной строки. Другие предназначены для запуска через веб-сервер.

Все функции CloudFusion, о которых я вам рассказал, возвращают простые структуры данных — массивы строк. Однако функции, которые я буду использовать позже в этой статье, возвращают более сложную структуру данных, называемую ResponseCore . S3 возвращает свои результаты в виде XML-документа; CloudFusion анализирует XML с помощью пакета PHP SimpleXML и включает проанализированные объекты в ответ, где на них можно ссылаться по имени. [ 1 ]

предупреждение: CloudFusion стал AWS SDK для PHP

Со времени, когда мы опубликовали книгу и первую статью в этой серии, библиотека CloudFusion стала официальным AWS SDK для PHP . Этот выпуск поставляется с улучшенной поддержкой регионов AWS, а также с множеством других улучшений. Это может означать, что вам нужно будет внести некоторые небольшие изменения в код, если вы не используете версию 2.5 библиотеки , но, поскольку новый SDK 1.0 полностью основан на старой кодовой базе CloudFusion, эти изменения должны быть незначительными, и мало и далеко друг от друга.

Следующий код вызывает S3 для отображения первых 1000 объектов в BOOK_BUCKET , а затем вызывает print_r функцию PHP print_r для отображения результирующего дерева объектов:


Результирующий вывод слишком длинный, чтобы отобразить его целиком (465 строк для моих сегментов). Давайте посмотрим на некоторые выдержки вместо этого. Вот первая часть:

  $ php list_bucket_objects_raw.php ResponseCore Object[header] => Array( [x-amz-id-2] => Ya7yAuUClv7HgR6+JJpz0sYDM1m4/Zy+d0Rmk5cSAu+qV+v+6➥9gLSHlytlD77wAn [x-amz-request-id] => 14AA13F3F0B76032 [date] => Thu, 28 May 2009 06:51:26 GMT [content-type] => application/xml [transfer-encoding] => chunked [connection] => close [server] => AmazonS3 [_info] => Array ( https%3A%2F%2Fwww.sitepoint.com => https://sitepoint-aws-cloud-book.s3.amazonaws.com/ [content_type] => application/xml ⋮ 

Первая строка указывает, что данные имеют тип ResponseCore . Далее мы найдем несколько стандартных массивов PHP. Если нам нужно, мы можем получить доступ к данным следующим образом:

  $ Res-> заголовок [ 'Transfer-Encoding'] $ res-> заголовок [ '_ Информация о'] [ 'URL'] 

$res является объектом, а header является одной из переменных экземпляра объекта, поэтому доступ к нему осуществляется с помощью оператора -> . Переменная экземпляра header является массивом PHP, поэтому доступ к ее членам осуществляется с использованием синтаксиса массива.

Во второй строке член _info header сам по себе является массивом, поэтому второй набор скобок используется для доступа к значению url внутри.

Чуть дальше в выводе мы находим следующее:

 [body] => SimpleXMLElement Object( [Name] => sitepoint-aws-cloud-book ⋮ 

Переменная экземпляра body имеет тип SimpleXMLElement . Он начинается с переменной экземпляра Name , к которой можно получить доступ как $res->body->Name .

Еще дальше мы наконец-то нашли то, для чего мы пришли — список объектов в корзине:

 [Contents] => Array( [0] => SimpleXMLElement Object ( [Key] => images/2008_shiller_housing_projection.jpg [LastModified] => 2009-05-22T23:44:58.000Z [ETag] => "e2d335683226059e7cd6e450795f3485" [Size] => 236535 [Owner] => SimpleXMLElement Object ( [ID] => 7769a42be4e57a034eeb322aa8450b3536b6ca56037c06ef19b1e1➥eabfeaab9c [DisplayName] => jeffbarr ) [StorageClass] => STANDARD ) ⋮ 

Вы можете видеть, что body содержит переменную экземпляра с именем Contents , которая является другим массивом, содержащим все файлы в корзине. Каждый файл в SimpleXMLElement объектом SimpleXMLElement ; у каждого есть ETag Key , ETag , Size , Owner и StorageClass , доступ к которым осуществляется следующим образом:

  $ Res-> Автодиагностика> Содержание [0] -> Основные $ res-> Автодиагностика> Содержание [0] -> ETag $ res-> Автодиагностика> Содержание [0] -> Размер $ res-> Автодиагностика> Содержание [0] -> Owner-> ID $ res-> Автодиагностика> Содержание [0] -> Owner-> отображаемое_имя $ res-> Автодиагностика> Содержание [0] -> Класс складирования 

Конечно, вы можете использовать промежуточные переменные, чтобы сделать этот код короче или эффективнее.

Вам может быть интересно, откуда берутся названия объектов ( Contents , Key , Size и т. Д.). Метод list_objects делает HTTP- GET к S3, чтобы получить список первых 1000 объектов в корзине. Запрос возвращает XML-документ, а CloudFusion анализирует и возвращает его как объект body . Имена объектов берутся непосредственно из тегов XML в документе.

Если бы мы изменили предыдущий скрипт, чтобы распечатать некоторые из этих значений, он может выглядеть следующим образом:

  #! / usr / bin / php <? phperror_reporting (E_ALL); require_once ('cloudfusion.class.php'); require_once ('include / book.inc.php'); $ s3 = new AmazonS3 (); $ res = $ s3-> list_objects (BOOK_BUCKET);  print ("Bucket Url:". $ res-> header ['_ info'] ['url']. "n"); print ("Bucket Name:". $ res-> body-> Name. "n") ; print ("Первый ключ:". $ res-> body-> Contents [0] -> Key. "n"); print ("Второй ключ:". $ res-> body-> Contents [1] -> Ключ. "N");  Выход (0);?> 

В приведенном выше примере мы выводим URL и имя корзины, а затем ключи первых двух элементов в корзине.

Теперь мы подошли к концу объезда. Я надеюсь, что поездка была сценической, все же образовательной. Далее мы будем использовать эти новые знания для создания очень удобной функции полезности.

Прежде чем мы сможем написать скрипт, который выводит список всех объектов в корзине на веб-странице, мы сначала должны написать довольно сложную функцию. Мы добавим эту функцию в наш файл book.inc.php и назовем ее getBucketObjects :


Эта функция более сложна, чем все, что вы видели до сих пор, но вам не о чем беспокоиться. Ранее я говорил вам, что один запрос «списка сегментов» к S3 вернет самое большее 1000 ключей, независимо от того, сколько ключей находится в сегменте. Наша функция getBucketObjects просто снова и снова вызывает list_objects пока S3 не скажет, что больше нет объектов для возврата:

1

Наша функция принимает три аргумента: объект AmazonS3 , AmazonS3 S3 и значение префикса, по умолчанию равное пустой строке.

2

Мы используем цикл do … while while, чтобы тело цикла всегда выполнялось хотя бы один раз.

3

Каждый раз, когда я вызываю list_objects , я list_objects значение с именем $next . В первый раз в цикле $next является пустой строкой, а list_objects начинается с начала (в алфавитном порядке) сегмента. На последующих итерациях цикла $next устанавливается на окончательный ключ, возвращаемый на предыдущей итерации. Это говорит S3 начать извлечение ключей в алфавитном порядке после последнего ключа предыдущей итерации.

4

Если вызов list_objects не удался, функция возвращает list_objects .

5

Мы извлекаем массив Contents из тела ответа, возвращаемого на наш вызов list_objects , а затем перебираем значения, сохраняющие каждое из них в массиве $objects . Этот массив в конечном итоге будет нашим возвращаемым значением.

6

Данные, возвращаемые вызовом list_objects включают элемент с именем IsTruncated . Если это значение является строкой "true" , листинг будет неполным, и в нем будет найдено больше объектов. Это условие также используется для управления циклом.

7

Если список неполон, мы устанавливаем значение $next чтобы начать следующую итерацию.

8

Когда цикл завершается, возвращается массив $objects .

Поместите его вместе, и эта функция извлекает все объекты из корзины, помещает их все в один массив и возвращает массив.

С этой функцией создание списка объектов в корзине становится легким. Вот все, что нам нужно сделать:


Этот код генерирует веб-страницу и может принимать необязательный аргумент корзины в строке запроса URL. Давайте разорвем это на части и посмотрим, как это работает:

1

Этот код проверяет, был ли указан аргумент bucket . Если это так, то он используется как значение $bucket . В противном случае используется значение по умолчанию, константа BOOK_BUCKET .

2

Здесь мы вызываем нашу пользовательскую функцию getBucketObjects которая выбирает список объектов в данном сегменте и сохраняет их в массиве $objects .

3

Следующий шаг — перебрать массив и обработать каждый.

4

Мы сохраняем три значения для каждого объекта в массиве $fileList : URL-адрес объекта, ключ (который мы храним как name ) и размер (преобразуется в целое число и форматируется как число).

5

Мы включаем наш HTML-шаблон для вывода значений в массиве $fileList .

Вот как list_bucket_objects.html.php HTML-шаблон list_bucket_objects.html.php :


Шаблон $fileList массив $fileList и создает строку таблицы для каждого файла, помещая ссылку на файл в первом столбце и размер файла во втором столбце.

Рисунок 1, «Список объектов в корзине S3» показывает, как это выглядит (я уже загрузил некоторые файлы в мою корзину).


Возможно, вы заметили тот факт, что теперь у нас есть все детали, необходимые для создания простого файлового браузера S3. Я оставлю это как вызов для вас. Всего лишь немного поработав, вы сможете соединить list_buckets_page.php и list_bucket_objects_page.php .