Storage OnLine: Utilizzare API S3 con PHP per salvare, modificare e cancellare i dati dallo storage
Di seguito, come salvare oggetti nei bucket, modificarli e cancellarli, utilizzando la libreria S3.php.
Al termine di questo esempio, verrà realizzato un vero e proprio file browser per gestire i propri oggetti nello Storage OnLine
Upload di file
L'operazione di caricamento file verrà effettuata in due fasi:
- upload del file dal computer dell'utente al proprio web server;
- trasferimento dello stesso sullo Storage OnLine.
L'upload su server via HTTP POST è una funzionalità molto comune, implementata in molte applicazioni PHP anche e soprattutto tramite librerie di terze parti che ne semplificano le gestione; per essere il più generici e compatibili possibile, quindi il codice utilizzerà solamente le funzionalità standard di una comune configurazione PHP. Affinché ciò sia possibile però; è necessario che alcune direttive PHP (solitamente nel file php.ini) siano configurate correttamente:
- file_uploads: deve essere posto a On;
- upload_max_filesize: indica la dimensione massima dei file che è possibile caricare via HTTP;
- post_max_size: indica la dimensione massima della richiesta HTTP POST, e deve essere necessariamente superiore a upload_max_filesize perché spesso vengono inviati altri parametri oltre al file stesso.
Creare, quindi, un file uploadFile.php nella stessa cartella delle altre pagine PHP ed inserire questo codice:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <?php try { // configurazione require_once 'conf/configuration.php'; // azioni $bucketName = $_REQUEST['bucketName']; $prefix = isset($_REQUEST['prefix']) ? $_REQUEST['prefix'] : ''; $parent = isset($_REQUEST['parent']) ? $_REQUEST['parent'] : ''; if ('POST' == $_SERVER['REQUEST_METHOD']) { // gestisci upload if ($_FILES['file']['error'] > 0) { throw new Exception('Errore durante l\'upload del file', $_FILES['file']['error']); } if (is_uploaded_file($_FILES['file']['tmp_name'])) { $input = S3::inputFile($_FILES['file']['tmp_name']); $uri = $prefix . $_FILES['file']['name']; if (S3::putObject($input, $bucketName, $uri)) { $message = 'Il file è stato caricato correttamente nel bucket'; } else { $message = 'Problemi nella creazione dell\'oggetto nel bucket'; } } } } catch(Exception $ex) { $errorMessage = "Si è verificato un errore (". $ex->getCode()."):\n".$ex->getMessage(); $errorMessage = nl2br(htmlspecialchars($errorMessage, ENT_NOQUOTES, 'UTF-8')); } ?> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>S3 API test</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <?php if (isset($errorMessage)) { ?> <div class="errorMessage"> <?php echo $errorMessage; ?> </div> <?php } else { ?> <h3>Carica un file</h3> <?php if (isset($message)) { ?> <div class="message"> <?php echo $message; ?> </div> <?php } $backUrl = 'listObjectsAdvanced.php?bucketName=' . urlencode($bucketName) . '&prefix=' . urlencode($prefix) . '&parent=' . urlencode($parent); echo '<p><a href="' . $backUrl . '">Indietro</a></p>'; ?> <p>Bucket: <em><?php echo htmlspecialchars($bucketName, ENT_NOQUOTES, 'UTF-8');?></em></p> <p>Directory: <em><?php echo htmlspecialchars('/'.$prefix,ENT_NOQUOTES,'UTF-8');?></em></p> <form action="uploadFile.php" method="post" enctype="multipart/form-data"> <input type="hidden" name="bucketName" value="<?php echo htmlspecialchars($bucketName, ENT_NOQUOTES, 'UTF-8');?>" /> <input type="hidden" name="prefix" value="<?php echo htmlspecialchars($prefix, ENT_NOQUOTES, 'UTF-8');?>" /> <input type="hidden" name="parent" value="<?php echo htmlspecialchars($parent, ENT_NOQUOTES, 'UTF-8');?>" /> <label for="file">Scegli un file da caricare:</label> <input type="file" name="file" id="file" /> <button type="submit">Invia</button> </form> <?php } ?> </body>
Osservando il codice:
- inclusione della configurazione e delle librerie;
- recupero dei parametri della richiesta PHP, notare l'utilizzo di $_REQUEST per gestire sia richieste di tipo GET che POST;
- in caso di POST si suppone che esista un file nella cartella temporanea;
- si utilizza il metodo S3::inputFile() per trasformare un nome di file in un array utilizzabile dalla classe S3.php;
- il metodo S3::putObject() si occupa quindi del trasferimento vero e proprio dei byte nel Storage;
- gestione degli errori tramite il meccanismo delle Exception e try/catch.
La maggior parte del codice php si trova, quindi, isolato nella prima parte del file, mentre il codice HTML che crea la pagina è isolato nella seconda parte. Qui, l'unico codice php presente è quello necessario a valutare se mostrare il form o un messaggio d'errore; inoltre ci limitiamo a utilizzare le variabili in lettura, ad esempio per costruire il form o per creare i link di rimando alla pagina listObjectsAdvanced.php (il file browser che realizzato in questa guida).
Una nota sulla sicurezza: utilizzare correttamente le funzioni htmlspecialchars() e urlencode(), visto che i bucket e gli oggetti possono avere dei nomi contenenti caratteri speciali per l'HTML come <, >, &, o comunque non compatibili con un URL. Ecco, quindi come e quando utilizzarle:
- htmlspecialchars() : va utilizzata per inserire una stringa all'interno del codice HTML. Questa funzione sostituisce i caratteri <, >, & (e molti altri) con i corrispondenti codici entità: < > e &
- urlencode(): va utilizzata per lo stesso motivo di cui sopra, ma durante l'aggiunta di parametri ad un URL. Questa funzione traduce correttamente i caratteri non-standard, permettendone il corretto passaggio come parametri.
Osservare, infine, alcune caratteristiche molto importanti del codice HTML per il form di upload:
- action="uploadFile.php" rimanda sulla pagina stessa, cioè la pagina ricarica se stessa dopo il submit;
- method="post" specifica che la richiesta sarà di tipo HTTP POST;
- enctype="multipart/form-data" indica che, insieme ai parametri, si sta inviando anche un file;
- i vari <input type="hidden"> riportano i parametri ricevuti dalla pagina: bucketName, prefix, parent. In questo modo, una volta eseguito l'upload, si potrà tornare facilmente al file browser per verificare l'effettivo caricamento del file.