Guide

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à: &lt; &gt; e &amp;
  • 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.

Risorse