Windows Azure oferuje trzy podstawowe mechanizmy przechowywania danych. Każdy z nich przeznaczony jest dla innego typu danych i każdy z nich oferuje inne możliwości. Dzisiaj skupimy się na niestandardowym zastosowaniu blobów, czyli pojemników na dane binarne. Jeśli nie wiecie czym są bloby, możecie zapoznać się z ich opisem tutaj.
Problem
Problem z jakim się dzisiaj zmierzymy znany jest wszystkim, którzy mieli do czynienia z aplikacją przechowującą pliki wgrywane przez użytkowników. Najwięcej kłopotu w tego typu aplikacji przysparza przechowywanie informacji o zmianach jakie użytkownik wprowadził do pliku. Najpopularniejszym rozwiązaniem tego problemu jest przechowywanie poprzednich wersji pliku w osobnych katalogach, ewentualnie zmiana nazwy pliku i dodanie do niego znacznika czasu. Do tego dochodzi jeszcze baza danych, w której przechowywane są informacje o użytkowniku wprowadzającym zmiany (czasami więcej niż jeden użytkownik mają możliwość nadpisania pliku), dacie wprowadzenia zmian oraz szereg innych niezbędnych informacji.
Rozwiązanie
Azure Storage, a dokładniej bloby, oferują interesującą funkcjonalność nazwaną snapshot. Dzięki niej możemy stworzyć migawkę pliku wraz z jej dokładnym opisem. Następnie jeśli zajdzie taka potrzeba możemy odwołać się do dowolnej migawki oraz informacji z nią związanych. W takim modelu baza danych wymagana jest do przechowywania jedynie identyfikatora migawki. Cała reszta siedzi zaszyta w blobie.
Przygotowanie środowiska
W dzisiejszym przykładzie wykorzystamy Windows Azure jedynie jako magazyn danych. Aplikacja uzyskująca dostęp chmury będzie znajdować się w innej lokalizacji. Podobnie jak ostatnim razem zaprezentowany zostanie jedynie szkielet aplikacji, który został maksymalnie uproszczony.
Nasze środowisko będzie się składać z jednego kontenera oraz jednego bloba. Blob ten będzie posiadał dwie migawki wraz z informacją o użytkowniku, który ją wykonał. Do przygotowania środowiska wykorzystamy prosty skrypt.
require_once 'Microsoft/WindowsAzure/Storage.php';
require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
// Dane wymagane do zalogowania się na konto Windows Azure
// W przykładzie logujemy się do konta lokalnego
$host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB;
$accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT;
$accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY;
$storageBlob = new Microsoft_WindowsAzure_Storage_Blob($host, $accountName, $accountKey);
// Usuń kontener i stwórz nowy
if($storageBlob->containerExists('wersjonowanie')) {
$storageBlob->deleteContainer('wersjonowanie');
}
$storageBlob->createContainer('wersjonowanie');
// Ustawienie kontenera jako publiczny
$storageBlob->setContainerAcl('wersjonowanie', Microsoft_WindowsAzure_Storage_Blob::ACL_PUBLIC_CONTAINER);
// Kowalski uploadował plik
$storageBlob->putBlob('wersjonowanie', 'plik.jpg', '/ulopadowany/plik/1.jpg', array('user' => 'Kowalski'));
// Nowak uploadował plik
// Wykonujemy migawkę pliku. W prawdziwej aplikacja jej identyfikator powinien trafić do bazy.
echo $storageBlob->snapshotBlob('wersjonowanie', 'plik.jpg') . PHP_EOL;
// Nadpisujemy bloba
$storageBlob->putBlob('wersjonowanie', 'plik.jpg', '/ulopadowany/plik/2.jpg', array('user' => 'Nowak'));
// admin uploadował plik
// Wykonujemy kolejną migawkę pliku i zapisujemy jej identyfikator
echo $storageBlob->snapshotBlob('wersjonowanie', 'plik.jpg') . PHP_EOL;
// Nadpisujemy bloba
$storageBlob->putBlob('wersjonowanie', 'plik.jpg', '/ulopadowany/plik/3.jpg', array('user' => 'admin'));
W powyższym kodzie na uwagę zasługują dwa elementy. Pierwszym jest dodawanie bloba. W tym miejscu (a dokładniej w czwartym argumencie metody pubBlob), mamy możliwość dodania do bloba metadanych w postaci tablicy klucz –> wartość. Metadane nie mogą zawierać więcej niż 8KB informacji, a klucz nie może być dłuższy niż 1024 znaki. Mimo niewielkiego rozmiaru, metadane w zupełności wystarczą do przechowania wszystkich niezbędnych informacji o blobie (np. nazwa użytkownika).
Drugim elementem jest moment wykonania migawki. Odpowiedzialna za to metoda snapshotBlob, zwraca unikalny w obrębie bloba identyfikator w postaci wartości DateTime. Aby móc później odwołać się do konkretnej migawki, musimy ten identyfikator zapisać, np. w bazie danych.
Wyświetlanie historii pliku
require_once 'Microsoft/WindowsAzure/Storage.php';
require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
$host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB;
$accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT;
$accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY;
$storageBlob = new Microsoft_WindowsAzure_Storage_Blob($host, $accountName, $accountKey);
// pobrane z bazy identyfikatory migawek
$snapshotId1 = '2011-01-25T08:15:14.7130000Z';
$snapshotId2 = '2011-02-01T16:09:04.8730000Z';
// pobranie metadanych z bloba oraz migawek
$meta = $storageBlob->getBlobMetadata('wersjonowanie', 'plik.jpg');
$metas1 = $storageBlob->getBlobMetadata('wersjonowanie', 'plik.jpg', $snapshotId1);
$metas2 = $storageBlob->getBlobMetadata('wersjonowanie', 'plik.jpg', $snapshotId2);
// wyświetlenie zdjęć oraz ich autorów
echo 'Aktualne zdjęcie (autor: ' . $meta['user'] . ')<br />';
echo '<img src="zdjecie.php" width="300" />';
echo '<br /><br />';
echo 'Snapshot 1 (autor: ' . $metas1['user'] . '):<br />';
echo '<img src="zdjecie.php?snapshotid=' . urlencode($snapshotId1) . '" width="300" />';
echo '<br /><br />';
echo 'Snapshot 2 (autor: ' . $metas2['user'] . '):<br />';
echo '<img src="zdjecie.php?snapshotid=' . urlencode($snapshotId2) . '" width="300" />';
echo '<br /><br />';
Jak widać na powyższym kodzie, operacje na migawkach przeprowadza się w identyczny sposób jak na aktualnej wersji bloba. Jedyną różnicą jest konieczność użycia zapisanego wcześniej identyfikatora migawki.
Ostatnim elementem układanki jest skrypt pobierający zawartość bloba i zwracającego go jako obrazek (zdjęcie.php).
require_once 'Microsoft/WindowsAzure/Storage.php';
require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
$host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB;
$accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT;
$accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY;
$storageBlob = new Microsoft_WindowsAzure_Storage_Blob($host, $accountName, $accountKey);
header('Content-Type: image/jpg');
// jeśli nie ma identyfikatora migawki, pobierz zawartość aktualnego bloba
if(!isset($_GET['snapshotid'])) {
echo $storageBlob->getBlobData('wersjonowanie', 'plik.jpg');
}
else {
// pobierz zawartość migawki
echo $storageBlob->getBlobData('wersjonowanie', 'plik.jpg', urldecode($_GET['snapshotid']));
}
Voila!
W ten oto sposób stworzyliśmy proste i skuteczne zarazem wersjonowanie plików uploadowanych przez użytkownika. Nie musimy się na tym zatrzymywać. W przypadku większej ilości informacji, które powinny znaleźć się w opisie bloba, można skorzystać z tabel. Metadane zawierałyby jedynie klucz partycji oraz klucz wiersza.
Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...
Zwiń
Czytaj na blogu autora...