¿Cómo puedo agregar un campo de carga de imagen directamente a un panel de escritura personalizado?

60

Agregué una nueva página en "Páginas" en el administrador de wordpress y agregué varios campos personalizados. También me gustaría poder agregar un campo de imagen de carga al editor de páginas. ¿Hay alguna forma de hacerlo a través de campos personalizados?

¿O hay una dirección diferente que debo tomar si necesito esta habilidad?

    
pregunta Will 19.11.2010 - 19:31

2 respuestas

107

Para cualquier persona que quiera saber más sobre la carga de archivos, aquí hay una introducción rápida que cubre los principales temas y los puntos débiles. Esto está escrito con WordPress 3.0 en una caja de Linux en mente, y el código es solo una descripción básica para enseñar los conceptos. Estoy seguro de que algunas personas aquí podrían ofrecer consejos para mejorar la implementación.

Describe tu enfoque básico

Hay al menos tres formas de asociar imágenes con publicaciones: usando un campo post_meta para almacenar la ruta de la imagen, usando un campo post_meta para almacenar la ID de la biblioteca de medios de la imagen (más sobre esto más adelante), o asignando la imagen a la publicación como un archivo adjunto. Este ejemplo utilizará un campo post_meta para almacenar la identificación de la biblioteca de medios de la imagen. YMMV.

Codificación multiparte

Por defecto, WordPress 'create & Las formas de edición no tienen enctype. Si desea cargar un archivo, deberá agregar un "enctype = 'multipart / form-data'" a la etiqueta del formulario; de lo contrario, la colección $ _FILES no se eliminará en absoluto. En WordPress 3.0, hay un gancho para eso. En algunas versiones anteriores (no está seguro de los detalles), debe reemplazar la etiqueta del formulario.

function xxxx_add_edit_form_multipart_encoding() {

    echo ' enctype="multipart/form-data"';

}
add_action('post_edit_form_tag', 'xxxx_add_edit_form_multipart_encoding');

Crear el cuadro Meta y el campo de carga

No voy a ir muy lejos en la creación de meta box ya que la mayoría de ustedes probablemente ya saben cómo hacerlo, pero solo diré que solo necesita una meta box simple con un campo de archivo. En el siguiente ejemplo, he incluido algo de código para buscar una imagen existente y mostrarla si existe. También he incluido algunas funciones simples de error / retroalimentación que pasan errores usando un campo post_meta. Querrá cambiar esto para usar la clase WP_Error ... es solo para demostración.

function xxxx_render_image_attachment_box($post) {

    // See if there's an existing image. (We're associating images with posts by saving the image's 'attachment id' as a post meta value)
    // Incidentally, this is also how you'd find any uploaded files for display on the frontend.
    $existing_image_id = get_post_meta($post->ID,'_xxxx_attached_image', true);
    if(is_numeric($existing_image_id)) {

        echo '<div>';
            $arr_existing_image = wp_get_attachment_image_src($existing_image_id, 'large');
            $existing_image_url = $arr_existing_image[0];
            echo '<img src="' . $existing_image_url . '" />';
        echo '</div>';

    }

    // If there is an existing image, show it
    if($existing_image_id) {

        echo '<div>Attached Image ID: ' . $existing_image_id . '</div>';

    } 

    echo 'Upload an image: <input type="file" name="xxxx_image" id="xxxx_image" />';

    // See if there's a status message to display (we're using this to show errors during the upload process, though we should probably be using the WP_error class)
    $status_message = get_post_meta($post->ID,'_xxxx_attached_image_upload_feedback', true);

    // Show an error message if there is one
    if($status_message) {

        echo '<div class="upload_status_message">';
            echo $status_message;
        echo '</div>';

    }

    // Put in a hidden flag. This helps differentiate between manual saves and auto-saves (in auto-saves, the file wouldn't be passed).
    echo '<input type="hidden" name="xxxx_manual_save_flag" value="true" />';

}



function xxxx_setup_meta_boxes() {

    // Add the box to a particular custom content type page
    add_meta_box('xxxx_image_box', 'Upload Image', 'xxxx_render_image_attachment_box', 'post', 'normal', 'high');

}
add_action('admin_init','xxxx_setup_meta_boxes');

Manejo de la carga de archivos

Este es el más importante: en realidad se encarga de la carga del archivo enganchándolo a la acción save_post. He incluido una función muy comentada a continuación, pero me gustaría tener en cuenta las dos funciones clave de WordPress que utiliza:

wp_handle_upload () hace toda la magia de, bueno, manejar la carga. Simplemente pase una referencia a su campo en la matriz $ _FILES y una variedad de opciones (no se preocupe demasiado por estas: la única importante que debe establecer es test_form = false. Confíe en mí). Sin embargo, esta función no agrega el archivo cargado a la biblioteca de medios. Simplemente realiza la carga y devuelve la ruta del nuevo archivo (y, fácilmente, también la URL completa). Si hay un problema, devuelve un error.

wp_insert_attachment () agrega la imagen a la biblioteca de medios y genera todas las miniaturas apropiadas. Simplemente pase una serie de opciones (título, estado de publicación, etc.) y la ruta LOCAL (no URL) al archivo que acaba de cargar. Lo mejor de colocar sus imágenes en la biblioteca de medios es que puede eliminar fácilmente todos los archivos más tarde llamando a wp_delete_attachment y pasándole el ID de la biblioteca de medios del elemento (que estoy haciendo en la función a continuación). Con esta función, también necesitarás usar wp_generate_attachment_metadata () y wp_update_attachment_metadata (), que hacen exactamente lo que esperas que hagan: generar metadatos para el elemento multimedia.

function xxxx_update_post($post_id, $post) {

    // Get the post type. Since this function will run for ALL post saves (no matter what post type), we need to know this.
    // It's also important to note that the save_post action can runs multiple times on every post save, so you need to check and make sure the
    // post type in the passed object isn't "revision"
    $post_type = $post->post_type;

    // Make sure our flag is in there, otherwise it's an autosave and we should bail.
    if($post_id && isset($_POST['xxxx_manual_save_flag'])) { 

        // Logic to handle specific post types
        switch($post_type) {

            // If this is a post. You can change this case to reflect your custom post slug
            case 'post':

                // HANDLE THE FILE UPLOAD

                // If the upload field has a file in it
                if(isset($_FILES['xxxx_image']) && ($_FILES['xxxx_image']['size'] > 0)) {

                    // Get the type of the uploaded file. This is returned as "type/extension"
                    $arr_file_type = wp_check_filetype(basename($_FILES['xxxx_image']['name']));
                    $uploaded_file_type = $arr_file_type['type'];

                    // Set an array containing a list of acceptable formats
                    $allowed_file_types = array('image/jpg','image/jpeg','image/gif','image/png');

                    // If the uploaded file is the right format
                    if(in_array($uploaded_file_type, $allowed_file_types)) {

                        // Options array for the wp_handle_upload function. 'test_upload' => false
                        $upload_overrides = array( 'test_form' => false ); 

                        // Handle the upload using WP's wp_handle_upload function. Takes the posted file and an options array
                        $uploaded_file = wp_handle_upload($_FILES['xxxx_image'], $upload_overrides);

                        // If the wp_handle_upload call returned a local path for the image
                        if(isset($uploaded_file['file'])) {

                            // The wp_insert_attachment function needs the literal system path, which was passed back from wp_handle_upload
                            $file_name_and_location = $uploaded_file['file'];

                            // Generate a title for the image that'll be used in the media library
                            $file_title_for_media_library = 'your title here';

                            // Set up options array to add this file as an attachment
                            $attachment = array(
                                'post_mime_type' => $uploaded_file_type,
                                'post_title' => 'Uploaded image ' . addslashes($file_title_for_media_library),
                                'post_content' => '',
                                'post_status' => 'inherit'
                            );

                            // Run the wp_insert_attachment function. This adds the file to the media library and generates the thumbnails. If you wanted to attch this image to a post, you could pass the post id as a third param and it'd magically happen.
                            $attach_id = wp_insert_attachment( $attachment, $file_name_and_location );
                            require_once(ABSPATH . "wp-admin" . '/includes/image.php');
                            $attach_data = wp_generate_attachment_metadata( $attach_id, $file_name_and_location );
                            wp_update_attachment_metadata($attach_id,  $attach_data);

                            // Before we update the post meta, trash any previously uploaded image for this post.
                            // You might not want this behavior, depending on how you're using the uploaded images.
                            $existing_uploaded_image = (int) get_post_meta($post_id,'_xxxx_attached_image', true);
                            if(is_numeric($existing_uploaded_image)) {
                                wp_delete_attachment($existing_uploaded_image);
                            }

                            // Now, update the post meta to associate the new image with the post
                            update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                            // Set the feedback flag to false, since the upload was successful
                            $upload_feedback = false;


                        } else { // wp_handle_upload returned some kind of error. the return does contain error details, so you can use it here if you want.

                            $upload_feedback = 'There was a problem with your upload.';
                            update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                        }

                    } else { // wrong file type

                        $upload_feedback = 'Please upload only image files (jpg, gif or png).';
                        update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                    }

                } else { // No file was passed

                    $upload_feedback = false;

                }

                // Update the post meta with any feedback
                update_post_meta($post_id,'_xxxx_attached_image_upload_feedback',$upload_feedback);

            break;

            default:

        } // End switch

    return;

} // End if manual save flag

    return;

}
add_action('save_post','xxxx_update_post',1,2);

Permisos, propiedad y seguridad

Si tiene problemas para cargar, es posible que tenga que ver con los permisos. No soy un experto en la configuración del servidor, así que corríjame si esta parte es defectuosa.

Primero, asegúrate de que tu carpeta wp-content / uploads existe, y es propiedad de apache: apache. Si es así, deberías poder establecer los permisos en 744 y todo debería funcionar. La propiedad es importante, incluso establecer los permisos en 777 a veces no ayuda si el directorio no se posee correctamente.

También debe considerar limitar los tipos de archivos cargados y ejecutados utilizando un archivo htaccess. Esto evita que las personas carguen archivos que no son imágenes y que ejecuten scripts disfrazados de imágenes. Probablemente debería buscar en Google para obtener más información autorizada, pero puede hacer una limitación de tipo de archivo simple como esta:

<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>
    
respondido por el MathSmath 23.11.2010 - 01:28
0

El código que proporcionó @MathSmath es correcto. Sin embargo, si maneja muchos campos de carga, o si desea cargar varios archivos, entonces tiene que modificarlo mucho.

Además, no utiliza la biblioteca de medios de WordPress para cargar archivos (lo que hace todo el trabajo sucio detrás de la escena).

Le sugiero que eche un vistazo a un complemento como Meta Box . El complemento admite ambas formas de cargar archivos:

  • A través de HTML5 input[type="file"] , que utiliza un código similar al de arriba (consulte docs ) y
  • A través de la biblioteca multimedia de WordPress (consulte docs ).

Puede ayudarlo a reducir el esfuerzo al escribir y mantener el código, especialmente cuando desea crear múltiples subidas.

Descargo de responsabilidad: soy el autor de Meta Box.

    
respondido por el Anh Tran 24.01.2018 - 03:57

Lea otras preguntas en las etiquetas