Як я можу додати поле для завантаження зображення безпосередньо на спеціальну панель запису?


62

Я додав нову сторінку в розділі "Сторінки" в адміністраторі Wordpress і додав кілька спеціальних полів. Я також хотів би мати можливість додати поле зображення для завантаження в редактор сторінки - чи є спосіб зробити це через користувацькі поля?

Або є інший напрямок, який мені потрібно взяти, якщо мені потрібна ця здатність?


перевірити плагін tdo-form, можливо, це найпростіше рішення
builtge

Це питання, ймовірно, пов’язане: wordpress.stackexchange.com/questions/4291/…
Гакре

Відповіді:


108

Для всіх, хто хоче дізнатися більше про завантаження файлів, ось короткий буквар, який висвітлює основні теми та больові моменти. Це написано з WordPress 3.0 на вікні Linux на увазі, і код є лише основним оглядом для викладання концепцій. Я впевнений, що деякі люди можуть запропонувати поради щодо покращення щодо впровадження.

Сформулюйте свій базовий підхід

Існують щонайменше три способи асоціювання зображень із публікаціями: використання поля post_meta для зберігання шляху зображення, використання поля post_meta для зберігання ідентифікатора медіатеки зображення (докладніше про це пізніше) або призначення зображення до публікації як вкладення . У цьому прикладі буде використано поле post_meta для зберігання ідентифікатора медіатеки зображення. YMMV.

Багаточастинне кодування

За замовчуванням WordPress 'створювати та редагувати форми не мають enteype Якщо ви хочете завантажити файл, вам потрібно буде додати "enctype = 'multipart / form-data" "в тег форми, інакше колекція $ _FILES взагалі не буде висунута. У WordPress 3.0 є гак для цього. У деяких попередніх версіях (не впевнені в специфіці) вам доведеться замінити рядок тегом форми.

function xxxx_add_edit_form_multipart_encoding() {

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

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

Створіть поле "Мета" та завантажте

Я не буду заглиблюватися в створення метаполев, оскільки більшість із вас, напевно, вже знають, як це зробити, але я просто скажу, що вам потрібен лише простий метабокс із полем файлу в ньому. У наведеному нижче прикладі я включив код, щоб шукати наявне зображення, і відображав його, якщо воно існує. Я також включив кілька простих функцій помилок / зворотних зв’язків, які передають помилки, використовуючи поле post_meta. Ви захочете змінити це для використання класу WP_Error ... це лише для демонстрації.

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');

Обробка завантаження файлу

Це найважливіше - фактично обробляти завантаження файлу, підключившись до дії save_post. Нижче я включив сильно коментовану функцію, але хочу зазначити дві ключові функції WordPress, які вона використовує:

wp_handle_upload () виконує всі чари, добре, обробляючи завантаження. Ви просто передаєте йому посилання на своє поле в масиві $ _FILES та масив опцій (не надто переживайте з цього приводу - єдиний важливий, який вам потрібно встановити, це тест_form = false. Довіртеся). Однак ця функція не додає завантажений файл до медіатеки. Він просто завантажує та повертає шлях до нового файлу (і, зручно, також повну URL-адресу). Якщо є проблема, вона повертає помилку.

wp_insert_attachment () додає зображення до медіатеки та генерує всі відповідні ескізи. Ви просто передаєте йому масив параметрів (заголовок, статус публікації тощо) та місцевий шлях (не URL) до файлу, який ви щойно завантажили. Чудова річ, що стосується розміщення ваших зображень у медіатеці - це те, що ви можете легко видалити всі файли пізніше, зателефонувавши до wp_delete_attachment та передавши йому ідентифікатор медіатеки предмета (що я роблю у функції нижче). За допомогою цієї функції вам також потрібно буде використовувати wp_generate_attachment_metadata () та wp_update_attachment_metadata (), які роблять саме те, що ви очікували б - генеруйте метадані для медіа-елемента.

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);

Дозволи, право власності та безпека

Якщо у вас є проблеми з завантаженням, це може мати відношення до дозволів. Я не є експертом у налаштуваннях сервера, тому, будь ласка, виправте мене, якщо ця деталь виграшна.

По-перше, переконайтеся, що ваша папка wp-content / uploads є і належить apache: apache. Якщо так, ви повинні мати можливість встановити дозволи на 744, і все повинно просто працювати. Власність важлива - навіть встановлення perms на 777 іноді не допоможе, якщо каталог належним чином не належить.

Слід також розглянути можливість обмеження типів завантажуваних та виконаних файлів за допомогою файлу htaccess. Це не дозволяє людям завантажувати файли, які не є зображеннями, та виконувати сценарії, замасковані під зображення. Ви, ймовірно, повинні google це для отримання більш авторитетної інформації, але ви можете зробити прості обмеження типу файлу, як це:

<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>

Дякую вам багато MathSmath! Тільки те, що мені було потрібно. Я б хотів, щоб я міг дати більше уваги на цю відповідь!
Міхал Мау

Відмінне пояснення! ТОЛЬКІ речі, які я дуже вдячний би вам розширити, - це зробити певні завантажені файли недоступними для загального користування. Іншими словами, якщо ви хочете створити певний пост-тип, у якому всі завантажені файли доступні лише користувачам з певними можливостями. Не могли б ви детальніше розглянути це?
NetConstructor.com

3
Для всіх, хто хоче завантажити файли на фронт, вам потрібно буде включити наступний код, щоб мати доступ до функції wp_handle_upload ():if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
Nick Budden

@ NetConstructor.com Я пропоную вам створити запитання, яке виходить за межі цієї відповіді.
hitautodestruct

0

Код, який надав @MathSmath, є правильним. Однак якщо ви обробляєте багато полів для завантаження або хочете завантажити декілька файлів, вам доведеться їх багато змінити.

Крім того, він не використовує медіатеку WordPress для завантаження файлів (що робить всю брудну роботу поза сценою).

Я б запропонував вам поглянути на плагін типу Meta Box . Плагін підтримує обидва способи завантаження файлів:

  • Через HTML5 input[type="file"], який використовує аналогічний код вище (див. Документи ) та
  • Через медіатеку WordPress (див. Документи ).

Це може допомогти вам зменшити зусилля щодо написання та збереження коду, особливо коли ви хочете створити кілька завантажень.

Відмова: Я автор Meta Box.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.