Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Upload delle immagini sul sito remoto

PHP ed FTP: scopriamo come effettuare l'upload delle immagini su un sito Internet remoto utilizzando anche le funzionalità fornite da jQuery ed AJAX
PHP ed FTP: scopriamo come effettuare l'upload delle immagini su un sito Internet remoto utilizzando anche le funzionalità fornite da jQuery ed AJAX
Link copiato negli appunti

In questo capitolo concluderemo il nostro percorso mostrando come effettuare l'upload di immagini su un sito remoto tramite jQuery e AJAX. Per cominciare definiamo una classe per gestire le richieste in AJAX.

require_once 'My_FTP.php';
class Ajax {
    public static function uploadImage() {
    }
}

Il file della classe include un riferimento alla classe che gestisce le sessioni FTP. Vogliamo salvare le immagini sia in locale che su server remoto. Per far questo creiamo un file PHP a cui far riferimento con jQuery per l'upload asincrono delle immagini:

require_once 'Ajax.php';
Ajax::uploadImage();

A questo punto passiamo all'implementazione effettiva del metodo Ajax::uploadImage().

public static function uploadImage() {
    $data = $_FILES;
        $result = true;
        $msg = 'Upload effettuato con successo!';
        if(!isset($data['image']['error']) || is_array($data['image']['error'])) {
            $result = false;
            $msg = 'Errore.';
        }
        switch ($data['image']['error']) {
            case UPLOAD_ERR_OK:
                break;
            case UPLOAD_ERR_NO_FILE:
                $result = false;
                $msg = 'Nessun file caricato.';
                break;
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                $result = false;
                $msg = 'File troppo grande.';
                break;
            default:
                $result = false;
                $msg = 'Errore.';
                break;
        }
        if ($data['image']['size'] > 1000000) {
            $result = false;
            $msg = 'File troppo grande.';
        }
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        if (false === $ext = array_search(
                $finfo->file($data['image']['tmp_name']),
                array(
                    'jpg' => 'image/jpeg',
                    'png' => 'image/png'
                ),
                true
            )) {
            $result = false;
            $msg = 'Il file non è un\'immagine.';
        }
        if(!move_uploaded_file($data['image']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/uploads/' . $data['image']['name'])) {
            $result = false;
            $msg = 'Impossibile spostare il file.';
        }
        if($result) {
            $upload = new My_FTP('192.168.1.4', 'username', 'password');
            $uploaded = $upload->upload('public_html/uploads/' . $data['image']['name'], $_SERVER['DOCUMENT_ROOT'] . '/uploads/' . $data['image']['name'], FTP_BINARY, 0755);
        }
        header('Content-Type: application/json');
        echo json_encode(array('result' => $result, 'msg' => $msg));
        exit;
}

Anche se operando in locale seguiamo la pratica di validare il file inviato verificandone dimensioni e tipo di contenuto prima di salvarlo su disco. Se l'esito della validazione è positivo (variabile $result), il file viene uploadato con un messaggio di successo. Altrimenti l'output JSON inviato al client riporterà un messaggio di errore.

Quando si gestisce AJAX con PHP bisogna impostare il tipo di contenuto tramite header HTTP e verificare che prima della chiamata a header() non sia stato inviato alcun output. Per output si intendono anche eventuali cookie impostati in precedenza.

Dopo aver inviato l'output, in questo caso una stringa JSON, è bene interrompere l'esecuzione dello script per evitare ad esempio che dopo la stringa sia presente dello spazio aggiuntivo non voluto. Tale spazio non ha effetto su PHP, ma può causare errori nel parsing JSON da parte del client.

Chi conosce HTML5 probabilmente penserà che avremmo potuto omettere la validazione del tipo di contenuto del file usando l'attributo accept:

<input type="file" name="image" id="image" accept="image/*">

Si tratta di una pessima soluzione in termini di sicurezza. L'attributo infatti può essere rimosso usando la console del browser, consentendo l'upload di file arbitrari. Lo scopo di questo attributo è un altro: quando si apre la finestra di dialogo per la scelta del file, i file che non corrispondono al tipo MIME scelto non sono selezionabili dalla GUI. Quindi usare solo questo attributo senza validare i file lato server è una pratica sbagliata.

HTML5 dispone anche delle File API associate agli elementi input di tipo file tramite l'array input.files. Esso contiene i riferimenti ai file selezionati per l'upload. Nel nostro caso image.files[0] conterrà il riferimento all'immagine.

Per inviare file con JavaScript si utilizza l'oggetto FormData che dispone del metodo append() per aggiungere una chiave ed un valore all'oggetto. Nel nostro caso la chiave avrà il valore image (deve essere lo stesso di quello contenuto nell'array globale $_FILES) e come valore i dati dell'immagine contenuti in image.files[0].

Con jQuery avremo:

$( "#upload-form" ).on( "submit", function( e ) {
        e.preventDefault();
        var $form = $( this );
        var formData = new FormData();
        var file = $( "#image" )[0].files[0];
        formData.append( "image", file );
        $form.find(".msg").remove();
        $.ajax({
            url: "/ajax.php",
            type: "POST",
            data: formData,
            processData: false,
            contentType: false,
            success: function( resp ) {
                $form.append('<p class="msg">' + resp.msg + '</p>');
                }
        });
});

Per usare l'oggetto FormData le proprietà processData e contentType devono essere impostate su false per impedire che jQuery intervenga sull'oggetto inviato cercando di rielaborarlo e modificarlo prima dell'invio della richiesta AJAX.

Stiamo usando jQuery per motivi di retrocompatibiltà qualora si volesse riutilizzare questa soluzione in altri contesti, attualmente JavaScript è però in grado di gestire l'upload dei file con soluzioni native molto più efficaci (come le Fetch API).

Ti consigliamo anche