Come caricare un'immagine con un form semplice?

5 mag 2013, 13:48:15
Visualizzazioni: 33.5K
Voti: 4

Sto sviluppando un plugin nella mia pagina del profilo e voglio creare un caricamento tramite il pulsante 'Sfoglia' e un campo 'Directory' che caricherà e restituirà l'URL dell'immagine. Non voglio utilizzare il media-upload.

Ho letto Imposta Immagine in Evidenza dal Form Frontend ma non riesco a capire il codice. Potete aiutarmi a risolvere questo problema?

0
Tutte le risposte alla domanda 3
2

Ci sono diverse parti.

Devi aggiungere un enctype al modulo del profilo.

function edit_form_type_wpse_98375() {
    echo ' enctype="multipart/form-data"';
}
add_action('user_edit_form_tag','edit_form_type_wpse_98375');

Poi aggiungi un campo al modulo.

function user_fields_wpse_98375($profileuser) {
  $_profile_photo = get_user_meta($profileuser->data->ID,'_profile_photo',true);

  echo '<h3>'.__('Dati Utente Aggiuntivi',THEME_TEXTDOMAIN).'</h3>';
    echo '<tr class="show-admin-bar">';
      echo '<th scope="row">'.__('Foto Profilo', THEME_TEXTDOMAIN).'</th>';
      echo '<td'.$tspan.'>';
        echo '<fieldset>';
          echo '<legend class="screen-reader-text"><span>'.__('Foto Profilo', THEME_TEXTDOMAIN).'</span></legend>';
          echo '<label for="profile_photo">';
            echo '<input name="profile_photo" type="file" id="profile_photo" value="" />';
          echo '</label><br />';
        echo '</fieldset>';
      echo '</td>';
    echo '</tr>';
  echo '</table>';
}
add_action('show_user_profile', 'user_fields_wpse_98375');
add_action('edit_user_profile', 'user_fields_wpse_98375');

E poi salva i dati.

function save_user_custom($id=false) {
  global $_FILES,$_POST;
  if (false === $id) return false;

  // salva immagine
  if (isset($_FILES)) {
    if (isset($_FILES['profile_photo'])){
      if (0 === $_FILES['profile_photo']['error']) {
        // Qui è dove salvi il file
        // Potresti usare wp_handle_upload
        // O usare l'API Filesystem
        // non sono sicuro di cosa vuoi fare
      }
    }
    unset($up);
  }
}
add_action('personal_options_update','save_user_custom');
add_action('edit_user_profile_update','save_user_custom');

wp_handle_upload è probabilmente il metodo più semplice. Dal Codex:

if ( ! function_exists( 'wp_handle_upload' ) ) 
    require_once( ABSPATH . 'wp-admin/includes/file.php' );
$uploadedfile = $_FILES['file'];
$upload_overrides = array( 'test_form' => false );
$movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
if ( $movefile ) {
    echo "Il file è valido ed è stato caricato con successo.\n";
    var_dump( $movefile);
} else {
    echo "Possibile attacco tramite caricamento file!\n";
}

L'input di tipo file funziona (per lo più) come qualsiasi altro input del modulo. Se gli dai un nome come my_uploads['profile_photo'] invece di solo profile_photo otterrai un array. Questo si rifletterà nella variabile $_FILES quando processerai l'invio del modulo. Puoi aggiungere quanti input file vuoi costruendo quell'array, o semplicemente dando loro nomi diversi. Per quanto riguarda l'aggiunta dinamica di input file, è abbastanza semplice con Javascript.

Riferimenti

http://codex.wordpress.org/Function_Reference/wp_handle_upload
http://codex.wordpress.org/Filesystem_API

5 mag 2013 16:36:21
Commenti

Grazie s_ha_dum ^_^ e questo è l'esempio che volevo veramente http://i165.photobucket.com/albums/u56/zectdropper/Capture_zpsea5fdfc7.png Spiegazione->il campo di upload può aggiungere o eliminare più elementi. Penso che dovrebbe salvarli come array. Come posso scriverli e salvarli in WordPress?

Monogot Monogot
5 mag 2013 17:12:01

E se devi testare gli errori, puoi usare questo hook: user_profile_update_errors

JMau JMau
5 mag 2013 18:06:28
1

Suppongo che tu non sia molto esperto con PHP e i caricamenti di file. Quindi inizierò con alcune basi e terminerò con una semplice classe.

Se non hai già letto le basi sui caricamenti di file con PHP, fallo ora. Nessuno te le spiegherà qui, è fuori tema.

Iniziamo con il modulo HTML di base

if( empty( $_FILES ) ) {
global $pagenow;
$url = admin_url( $pagenow );
?>
<!-- Il tipo di codifica dei dati, enctype, DEVE essere specificato come sotto -->
<form enctype="multipart/form-data" action="<?php echo $url; ?>" method="POST">
    <!-- MAX_FILE_SIZE deve precedere il campo di input del file -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Il nome dell'elemento di input determina il nome nell'array $_FILES -->
    Invia questo file: <input name="userfile" type="file" />
    <input type="submit" value="Invia File" />
</form>
<?php
} else {
    $imageupload = new File_Upload();
    $attachment_id = $imageupload->create_attachment();
    var_dump( $attachment_id );
}

Questo è abbastanza semplice. Se l'array superglobale $_FILES è vuoto, significa che nessun file è stato caricato, mostra il modulo di caricamento. Se non è vuoto, elabora il caricamento. Uso admin_url() e la variabile $pagenow per creare l'URL dell'azione. Se usi il modulo di caricamento nel frontend, devi usare home_url() o qualcosa di simile.

Dopo aver inviato il file con HTML, devi elaborare i file caricati. Questo verrà fatto nella classe File_Upload.

class File_Upload
{
    /**
     * Chiave dell'indice dal modulo di caricamento
     * @var string
     */
    public $index_key = '';

    /**
     * Copia dell'array superglobale $_FILES
     * @var array
     */
    public $files = array();

    /**
     * Costruttore
     * Imposta l'array files e indovina la chiave dell'indice
     */
    public function __construct(){

        if ( isset( $_FILES ) && ! empty( $_FILES ) ) {
            $this->files = $_FILES;
            $this->guess_index_key();
        }

    }

    /**
     * Imposta/sovrascrive la chiave dell'indice
     * Converte $name con il type casting (string)
     *
     * @param   string  $name   Nome della chiave dell'indice
     * @return  string  ::name  Nome della chiave dell'indice memorizzata
     */
    public function set_field_name_for_file( $name = '' ) {
        $this->index_key = ( ! empty( $name ) ) ? (string) $name : '';
        return $this->index_key;
    }

    /**
     * Converte il file caricato in un allegato WordPress
     *
     * @return  boolean     Indica se l'allegato è stato creato (true) o meno (false)
     */
    public function create_attachment(){

        // sposta il file caricato dalla cartella temporanea e crea i dati di base
        $imagedata = $this->handle_uploaded_file();

        // se lo spostamento fallisce, fermati qui
        /*
         * Per Produzione
         * Imposta e restituisce un oggetto di errore con WP_Error()
         */
        if ( empty( $imagedata ) )
            return false;

        /*
         * Per Produzione
         * Verifica se $imagedata contiene i valori attesi (e necessari)
         * Ogni metodo potrebbe fallire e restituire dati dannosi!!
         */
        $filename = $imagedata['filename'];

        // crea l'array dei dati dell'allegato
        $attachment = array(
                'guid'           => $imagedata['url'] . '/' . $filename,
                'post_mime_type' => $imagedata['type'],
                'post_title'     => preg_replace('/\.[^.]+$/', '', $filename ),
                'post_content'   => '',
                'post_status'    => 'inherit'
        );

        // inserisci l'allegato (posttype attachment)
        $attach_id = wp_insert_attachment( $attachment, $filename );

        // devi prima includere il file image.php
        // per far funzionare la funzione wp_generate_attachment_metadata()
        require_once( ABSPATH . 'wp-admin/includes/image.php' );

        /*
         * Per Produzione
         * Controlla $attach_data, wp_generate_attachment_metadata() potrebbe fallire
         * Verifica se wp_update_attachment_metadata() fallisce (restituisce false),
         * restituisci un oggetto di errore con WP_Error()
         */
        $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
        wp_update_attachment_metadata( $attach_id, $attach_data );

        return $attach_id;

    }

    /**
     * Gestisce il caricamento
     *
     * @return  array   $return_data    Array con informazioni sul file caricato
     */
    protected function handle_uploaded_file() {

        // ottieni i dati di base
        $return_data = wp_upload_dir();

        // ottieni il percorso temporaneo e il nome del file da $_FILES ($this->files)
        $tmp_file = ( isset( $this->files[$this->index_key] ) && ! empty( $this->files[$this->index_key] ) ) ?
            (string) $this->files[$this->index_key]['tmp_name'] : '';

        $tmp_name = ( isset( $this->files[$this->index_key] ) && ! empty( $this->files[$this->index_key] ) ) ?
            (string) $this->files[$this->index_key]['name'] : '';

        // fermati se qualcosa è andato storto
        if ( empty( $tmp_file ) )
            return false;

        // imposta il percorso del file
        $filepath = $return_data['filepath'] = $return_data['path'] . '/' . basename( $tmp_name );

        // sposta il file caricato dalla cartella temporanea alla cartella di upload
        move_uploaded_file( $tmp_file , $filepath );

        // imposta il nome del file
        $filename = $return_data['filename'] = basename( $filepath );

        // imposta il tipo di file
        /*
         * Per Produzione
         * Dovresti davvero, davvero verificare l'estensione e il tipo di file
         * su OGNI caricamento. Se non lo fai, è possibile caricare OGNI tipo di
         * file incluso codice dannoso.
         */
        $type = wp_check_filetype( $filename, null );
        $return_data['file_ext'] = ( isset( $type['ext'] ) && ! empty( $type['ext'] ) ) ?
        $type['ext'] : '';

        $return_data['type'] = ( isset( $type['type'] ) && ! empty( $type['type'] ) ) ?
        $type['type'] : '';

        // restituisci i risultati
        return $return_data;

    }

    /**
     * Prova a ottenere il primo indice da $_FILES
     *
     * @return  boolean     Indica se è stata trovata una chiave o meno
     */
    protected function guess_index_key() {

        $keys = array_keys( $_FILES );

        if ( ! empty( $keys ) ) {
            $this->index_key = $keys[0];
            return true;
        }

        return false;

    }

}

Questa è una classe di base e non è per la produzione! I caricamenti di file sono un argomento molto delicato, devi validare e sanificare tutti i dati da solo. Altrimenti è possibile che qualcuno carichi codice dannoso e hackerà il tuo server/blog/sito web!

Ora passo dopo passo cosa succede dove e quando.

Con la creazione di un'istanza della classe, la classe cerca di creare una copia dell'array superglobale $_FILES. Se lavori con array superglobali, non toccarli! Forse altre parti del codice (plugin o temi) hanno anche bisogno dei dati al loro interno. La prossima cosa che succede nel costruttore è che proviamo a indovinare la chiave dell'indice. Come sai, possiamo passare più di un file e $_FILES può contenere dati per tutti i file caricati. Se devi elaborare più di un file, scorri $_FILES e imposta la chiave dell'indice con set_field_name_for_file()

// ottieni gli indici da $_FILES
$keys = array_keys( $_FILES );
$upload_processor = new File_Upload();
foreach ( $keys as $key ) {
  $upload_processor->set_field_name_for_file( $key );
  $upload_processor->create_attachment();
}

set_field_name_for_file() è anche necessario se vuoi scegliere un campo specifico dal tuo modulo HTML, altrimenti la classe usa il primo indice che trova.

Il prossimo passo è gestire il file caricato. Il metodo create_attachment() chiama il metodo protetto handle_uploaded_file(), non devi farlo manualmente. Il metodo handle_uploaded_file() semplicemente raccoglie e imposta alcuni percorsi e nomi di file necessari.

L'ultimo passo è creare un allegato. create_atatchment() imposterà tutti i dati necessari e creerà un allegato per te. Il metodo restituisce l'ID dell'allegato, quindi puoi accedere a tutti i dati dell'allegato con get_post( [id] )

$imageupload = new File_Upload();
$attachment_id = $imageupload->create_attachment();
[qualche altro codice]        
$attachment = get_post( $attachment_id );
$image_url  = $attachment->guid;

printf( '<p><img src="%s"></p>', $image_url );

Qualche parola sulla gestione degli errori

Ho scritto alcuni suggerimenti nel codice della classe per l'ambiente di produzione. Come ho detto sopra, i caricamenti di file sono un argomento molto delicato. Devi controllare, validare e sanificare davvero tutto. WordPress ha una gestione degli errori integrata con WP_Error(). Usalo! E verifica se il caricamento è andato a buon fine con is_wp_error().

PHP può impostare alcuni messaggi di errore sul perché il caricamento è fallito se è fallito. Ma PHP non restituisce messaggi di testo chiari, restituisce codici di errore. Un metodo per convertire questi codici in testo chiaro potrebbe essere questo:

protected function guess_upload_error( $err = 0 ) {

$errcodes = array(
    'Errore sconosciuto',
    'Il file caricato supera la direttiva upload_max_filesize in php.ini.',
    'Il file caricato supera la direttiva MAX_FILE_SIZE specificata nel modulo HTML.',
    'Il file caricato è stato caricato solo parzialmente.',
    'Nessun file è stato caricato.',
    'Manca una cartella temporanea.',
    'Impossibile scrivere il file su disco.',
    'Un\'estensione PHP ha interrotto il caricamento del file. PHP non fornisce un modo per accertare quale estensione ha causato l\'interruzione del caricamento; esaminare l\'elenco delle estensioni caricate con phpinfo() potrebbe aiutare.'
);

return ( isset( $errcodes[$err] ) ) ?
    $errcodes[$err] : 'Errore sconosciuto';

}

Devi verificare se il caricamento è andato a buon fine, questo potrebbe essere così (nel metodo handle_upload_file())

// fermati se qualcosa è andato storto
if ( empty( $tmp_file ) ) {

    $code = ( isset( $this->files[$this->index_key]['error'] ) ) ?
        $this->files[$this->index_key]['error'] : 0;

    $msg = $this->guess_upload_error( $code );

    return new WP_Error( 'uploaderror', 'Caricamento fallito con messaggio: ' . $msg );
}

E poi devi gestire l'errore quando chiami la classe

if ( empty( $_FILES ) ) {

global $pagenow;
$url = admin_url( $pagenow );
?>
<!-- Modulo HTML-->
<?php
} else {
    $imageupload = new File_Upload();
    $attachment_id = $imageupload->create_attachment();

    if ( is_wp_error( $attachment_id ) ) {

        echo '<ol>';
        foreach ( $attachment_id->get_error_messages() as $err )
            printf( '<li>%s</li>', $err );
        echo '</ol>';

    } else {

        // fai qualcosa con l'allegato creato
        $attachment = get_post( $attachment_id );
        $image_url  = $attachment->guid;

        printf( '<p><img src="%s"></p>', $image_url );

    }
}

Ricorda sempre: Non lasciare mai un caricamento fallito non trattato!

5 mag 2013 17:58:02
Commenti

Nel modulo HTML di base, nel codice sopra non ho visto l'istruzione if prima dell'else

Monogot Monogot
5 mag 2013 23:52:29
0

Aggiungi codice nel file functions.php

add_action('wp_ajax_custom_action', 'custom_action');
add_action('wp_ajax_nopriv_custom_action', 'custom_action');
function custom_action() {

$post_id =12;
    //print_r($_FILES); exit;
    global $wpdb;
    //$response = array();

    if( $_FILES['uploadedfiles']) {

    $file = $_FILES['uploadedfiles'];
    require_once( ABSPATH . 'wp-admin/includes/admin.php' );
    $file_return = wp_handle_upload( $file, array('test_form' => false ) );
    if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) {
        return false;
    } else {
        $filename = $file_return['file'];
        $attachment = array(
            'post_mime_type' => $file_return['type'],
            'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
            'post_content' => '',
            'post_status' => 'inherit',
            'guid' => $file_return['url']
        );
        $attachment_id = wp_insert_attachment( $attachment, $file_return['url'] );
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
        wp_update_attachment_metadata( $attachment_id, $attachment_data );

        update_post_meta($post_id, '_thumbnail_id', $attachment_id);
        if( 0 < intval( $attachment_id ) ) {
          return $attachment_id;
        }
    }
    return false;

    }

    //$response['message'] = 'Immagine Caricata!!!';
    //echo json_encode($response);
    wp_die();


}
13 feb 2020 09:40:15