Использование переменной $_FILES в той же функции для загрузки изображений и файлов

Вопрос или проблема

Хочу начать с того, что я учусь и пытаюсь понять использование $_FILES и $file_handler, которые сводят меня с ума в этой функции для загрузки вложений из формы на фронтенде.

Что я обнаружил вчера в своем вопросе, так это то, что использование $_FILES в одной и той же функции приводит к его перезаписи, поэтому один добрый человек предложил изменить эту переменную на что-то другое, например, $whatever. Таким образом, оба файла могли бы быть обработаны и загружены, но, конечно, этого пока не происходит, и загружаются только файлы. У меня есть 2 поля формы с соответствующими именами:

  • Для изображений: name="moreimages"
  • Для файлов: name="morefiles"

В основном я пришел к такому коду на php:

if ($_FILES)
    {
        // Получаем загружаемые вложения
        $images = $_FILES['moreimages'];
        foreach ($images['name'] as $key => $value)
        {
            if ($images['name'][$key])
            {
                $image = array(
                    'name' => $images['name'][$key],
                    'type' => $images['type'][$key],
                    'tmp_name' => $images['tmp_name'][$key],
                    'error' => $images['error'][$key],
                    'size' => $images['size'][$key]
                );

                // Здесь я изменил переменную $_FILES на что-то другое
                $my_processed_images = array("moreimages" => $image);
                foreach ($my_processed_images as $image => $array)
                {
                    $newupload = project_images($image,$pid);
                }
            }
        }
        // Получаем загружаемые вложения
        $files = $_FILES['morefiles'];
        foreach ($files['name'] as $key => $value)
        {
            if ($files['name'][$key])
            {
                $file = array(
                    'name' => $files['name'][$key],
                    'type' => $files['type'][$key],
                    'tmp_name' => $files['tmp_name'][$key],
                    'error' => $files['error'][$key],
                    'size' => $files['size'][$key],
                    'post_mime_type' => $files['type'][$key]
                );
                $_FILES = array("morefiles" => $file);
                foreach ($_FILES as $file => $array)
                {
                    $uploadfile = project_file($file,$pid);
                }
            }
        }
    }

и мои функции выглядят так

function project_images($file_handler, $pid)
    {
        if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK) __return_false();
        require_once(ABSPATH . "wp-admin" . '/includes/image.php');
        require_once(ABSPATH . "wp-admin" . '/includes/file.php');
        require_once(ABSPATH . "wp-admin" . '/includes/media.php');
        $image_id = media_handle_upload( $file_handler, $pid );
        return $image_id;
    }
function project_file($file_handler, $pid)
    {
        if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK) __return_false();
        require_once(ABSPATH . "wp-admin" . '/includes/image.php');
        require_once(ABSPATH . "wp-admin" . '/includes/file.php');
        require_once(ABSPATH . "wp-admin" . '/includes/media.php');
        $file_id = media_handle_upload( $file_handler, $pid );
        update_post_meta($file_id,'is_prj_file','1');
        return $file_id;
    }

Я понимаю, что может быть проблема с моим $file_handler, но я не знаю, как с этим справиться. Что на самом деле происходит, так это то, что отладка $more_images возвращает null и не учитывается, а $_FILES во втором цикле загружен вместо этого. Можете помочь мне?

ИСПРАВЛЕНИЕ

Мои поля HTML формы выглядят так:

<input id="moreimages" accept="image/png, image/jpeg, image/gif" type="file" name="moreimages[]" >

<input id="morefiles" accept=".zip,.pdf,.rar,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.psd,.ai" type="file" name="morefiles[]" >

Кроме того, мой статус AJAX POST равен OK и отправляет эти параметры для moreimages:

Content-Disposition: form-data; name="moreimages[]"; filename="Screen Shot 2016-04-05 at 16.48.10.png"
Content-Type: image/png

PNG

и эти параметры для morefiles:

Content-Disposition: form-data; name="morefiles[]"; filename="articolo-slow-food-ararat.docx"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

Так что, я думаю, что проблема, снова, в том, как эти данные принимаются в php.

Я переопределил что-то. Я не делал валидацию и только построил структуру для функции валидации и загрузки. Вы можете валидировать файл по вашему усмотрению.

if ($_FILES)
    {
        // Получаем загружаемые вложения
        $images = $_FILES['moreimages'];
        $errors="";
        foreach ($images['name'] as $key => $value)
        {
            if ($images['name'][$key])
            {
                $image = array(
                    'name' => $images['name'][$key],
                    'type' => $images['type'][$key],
                    'tmp_name' => $images['tmp_name'][$key],
                    'error' => $images['error'][$key],
                    'size' => $images['size'][$key]
                );

                // Здесь я изменил переменную $_FILES на что-то другое
                $_FILES['moreimages'] = $image;
                if( is_wp_error( $moreimages = project_media_handle_upload('moreimages',$pid) ) )
                $errors .= $moreimages->get_error_message();

            }
        }
        // Получаем загружаемые вложения
        $files = $_FILES['morefiles'];
        foreach ($files['name'] as $key => $value)
        {
            if ($files['name'][$key])
            {
                $file = array(
                    'name' => $files['name'][$key],
                    'type' => $files['type'][$key],
                    'tmp_name' => $files['tmp_name'][$key],
                    'error' => $files['error'][$key],
                    'size' => $files['size'][$key],
                    'post_mime_type' => $files['type'][$key]
                );
                $_FILES['morefiles'] = $file;
                if( is_wp_error( $morefiles = project_media_handle_upload( 'morefiles', $pid, 'file' ) ) )
                $errors .= $morefiles->get_error_message();
            }
        }

        if( ! empty( $errors) )
        echo $errors;
    }

function image_and_files_validate_handle( $file ){
    // $file предоставляет все значения: размер, имя и т. д.
    // условное утверждение здесь и возвращаем каждый раз фиксированный ключ с сообщением
    $file['error'] =  'Файл недействителен';
    return $file;
}

function file_upload_validate_handle( $file ){
    // $file предоставляет все значения: размер, имя и т. д.
    // условное утверждение здесь и возвращаем каждый раз фиксированный ключ с сообщением
    $file['error'] =  $file['name']. ' недействительный формат.';
    return $file;
}

add_action( 'project_media_handle_upload', 'save_file_meta_content_id', 10, 2 );

function save_file_meta_content_id( $fid, $type ){
  if( $type == 'file')
  update_post_meta($fid,'is_prj_file','1'); 
}


function project_media_handle_upload( $file_id, $pid, $type= "image" ){

  $action = 'image_upload_action'; //  изменение пользовательского имени действия для легкости понимания

  if( $type !== 'image')
  $action = 'file_upload_action'; 

  if( function_exists('check_upload_size') )
  add_filter(  "{$action}_prefilter", 'check_upload_size'); // стандартный фильтр wordpress для проверки размера загрузки

  add_filter(  "{$action}_prefilter", 'image_and_files_validate_handle'); // обе условные проверки для изображений и файлов
  add_filter(  "file_upload_action_prefilter", 'file_upload_validate_handle');

  require_once(ABSPATH . "wp-admin" . '/includes/image.php');
  require_once(ABSPATH . "wp-admin" . '/includes/file.php');
  require_once(ABSPATH . "wp-admin" . '/includes/media.php');
  $result =  media_handle_upload( $file_id, $pid, array(), array( 
    'test_form' => false,
    'action' => $action
  ));

  if( ! is_wp_error($result) )
  do_action( 'project_media_handle_upload', $result, $type );   

  return $result;
}

Все были очень полезны, и я хочу СКАЗАТЬ СПАСИБО, ребята, за то, что помогли мне. Проблема, похоже, действительно заключалась в переменной $_FILES, которая перезаписывала себя в двух циклах. После нескольких попыток я нашел решение, которое работает для меня и позволяет загружать как изображения, так и файлы.

if ($_FILES)
    {
        // Сначала я объявил основные переменные
        $images = $_FILES['moreimages'];
        $files = $_FILES['morefiles'];

        // Затем я проверяю, пустые ли они. Вот и всё.
        if(!empty($images)) {
            foreach ($images['name'] as $key => $value)
            {
                if ($images['name'][$key])
                {
                    $image = array(
                        'name' => $images['name'][$key],
                        'type' => $images['type'][$key],
                        'tmp_name' => $images['tmp_name'][$key],
                        'error' => $images['error'][$key],
                        'size' => $images['size'][$key]
                    );
                    $_FILES = array("moreimages" => $image);
                    foreach ( $_FILES as $image => $array ) {
                        if ( $_FILES[$image]['error'] !== UPLOAD_ERR_OK ) __return_false();
                        require_once( ABSPATH . "wp-admin" . '/includes/image.php' );
                        require_once( ABSPATH . "wp-admin" . '/includes/file.php' );
                        require_once( ABSPATH . "wp-admin" . '/includes/media.php' );
                        $image_id = media_handle_upload( $image, $pid );
                        update_post_meta( $pid, 'project_image',$image_id);
                    }
                }

            }
        }
        if(!empty($files)) {
            foreach ($files['name'] as $key => $value)
            {
                if ($files['name'][$key])
                {
                    $file = array(
                        'name' => $files['name'][$key],
                        'type' => $files['type'][$key],
                        'tmp_name' => $files['tmp_name'][$key],
                        'error' => $files['error'][$key],
                        'size' => $files['size'][$key]
                    );
                    $_FILES = array("morefiles" => $file);
                    foreach ( $_FILES as $file => $array ) {
                        if ( $_FILES[$file]['error'] !== UPLOAD_ERR_OK ) __return_false();
                        require_once( ABSPATH . "wp-admin" . '/includes/image.php' );
                        require_once( ABSPATH . "wp-admin" . '/includes/file.php' );
                        require_once( ABSPATH . "wp-admin" . '/includes/media.php' );
                        $file_id = media_handle_upload( $file, $pid );
                        update_post_meta( $file_id, 'is_prj_file', '1');
                    }
                } 
            }
        }
    }

Возможно, этот код не совсем эффективен и идеален, но он выполняет свою задачу. Кроме того, в нем все еще нет серверной валидации файлов, которую я собираюсь реализовать позже, как было предложено ранее.

Ответ или решение

Доброго времени суток!

Я понимаю, что вы столкнулись с проблемой при работе с массивом $_FILES в функции загрузки файлов и изображений через форму на фронтенде. Давайте разберем вашу реализацию и предложим решение.

Проблема

Ваша основная проблема заключается в том, что вы пытаетесь обрабатывать файлы в одном и том же цикле, что может привести к перезаписи содержимого массива $_FILES, который вы используете для проверки загружаемых файлов. Это является причиной того, что некоторые файлы не обрабатываются должным образом.

Решение

Предлагаю улучшить ваш код, чтобы он стал более чистым и понятным. Вместо того чтобы перезаписывать массив $_FILES, я предлагаю отдельно обрабатывать изображения и документы, не заменяя его. Вы можете использовать временные массивы для упрощения управления данными.

Обновлённый Код

Вот переработанный вариант вашего кода:

if ($_FILES) {
    // Получаем файлы изображений
    $images = $_FILES['moreimages'];
    if (!empty($images) && is_array($images['name'])) {
        foreach ($images['name'] as $key => $value) {
            if ($images['name'][$key]) {
                $image = array(
                    'name' => $images['name'][$key],
                    'type' => $images['type'][$key],
                    'tmp_name' => $images['tmp_name'][$key],
                    'error' => $images['error'][$key],
                    'size' => $images['size'][$key]
                );

                // Временный массив для хранения данных о изображении
                $temp_files = array('moreimages' => $image);
                $_FILES = $temp_files;

                // Обработка загрузки изображения
                if ($_FILES['moreimages']['error'] === UPLOAD_ERR_OK) {
                    require_once(ABSPATH . 'wp-admin/includes/image.php');
                    require_once(ABSPATH . 'wp-admin/includes/file.php');
                    require_once(ABSPATH . 'wp-admin/includes/media.php');
                    $image_id = media_handle_upload('moreimages', $pid);
                    if (is_wp_error($image_id)) {
                        // Обработка ошибок
                        echo $image_id->get_error_message();
                    }
                }
            }
        }
    }

    // Получаем файлы документов
    $files = $_FILES['morefiles'];
    if (!empty($files) && is_array($files['name'])) {
        foreach ($files['name'] as $key => $value) {
            if ($files['name'][$key]) {
                $file = array(
                    'name' => $files['name'][$key],
                    'type' => $files['type'][$key],
                    'tmp_name' => $files['tmp_name'][$key],
                    'error' => $files['error'][$key],
                    'size' => $files['size'][$key]
                );

                // Временный массив для хранения данных о файле
                $temp_files = array('morefiles' => $file);
                $_FILES = $temp_files;

                // Обработка загрузки файла
                if ($_FILES['morefiles']['error'] === UPLOAD_ERR_OK) {
                    require_once(ABSPATH . 'wp-admin/includes/image.php');
                    require_once(ABSPATH . 'wp-admin/includes/file.php');
                    require_once(ABSPATH . 'wp-admin/includes/media.php');
                    $file_id = media_handle_upload('morefiles', $pid);
                    if (is_wp_error($file_id)) {
                        // Обработка ошибок
                        echo $file_id->get_error_message();
                    } else {
                        update_post_meta($file_id, 'is_prj_file', '1');
                    }
                }
            }
        }
    }
}

Примечания

  1. Проверка ошибок: Я добавил проверки на ошибки, чтобы вы могли видеть, если что-то пошло не так во время загрузки.
  2. Подключение файлов: Убедитесь, что требуемые файлы (image.php, file.php и media.php) загружаются каждый раз, когда вы вызываете функцию загрузки, чтобы избежать ошибок.
  3. Валидация файлов: Как вы отметили, валидация файлов ещё не реализована. Рекомендуется добавить проверки на допустимый тип и размер файлов для повышения безопасности вашего приложения.

Это должно позволить вам корректно загружать как изображения, так и другие файлы без перезаписи массива $_FILES. Если у вас есть дополнительные вопросы, не стесняйтесь обращаться!

Оцените материал
Добавить комментарий

Капча загружается...