Как сделать архив и загрузить в него рандом файлы wordpress?

Ссылка скопирована
1 ответ

Сайт на woordpress с woocommere
Привет, пока писал маркет по продаже аккаунтов возникла проблема

В кратце:
Есть цифровой товар и у него есть некое количество файлов, при условии, если человек при покупке выбрал один файл, то, он и получает один файл на странице "спасибо" (первый в списке файлов)
но, если он выбирает несколько товаров, то, они должны архивироваться в архив и выводится ссылкой на странице "спасибо"
Проблема в том, что архив постоянно получается пустым и повреждённым :(
У меня не получается нормально создать архив, и закинуть в него рандом файлы

У меня есть код в functions.php и archive-function.php, первый ведёт во второй

нужный кусок из файла functions.php :

include_once('archive-function.php');  add_action('woocommerce_thankyou', 'customize_thank_you_page');  function customize_thank_you_page($order_id) {     // Получение текущего заказа     $order = wc_get_order($order_id);      // Получение списка товаров в заказе     $items = $order->get_items();      // Получение общего количества товаров в заказе     $total_quantity = 0;      // Вычисляем общее количество товаров     foreach ($items as $item) {         $total_quantity += $item->get_quantity();     }      // Выводим информацию о товарах     echo '<p>';      if ($total_quantity === 1) {         echo 'Спасибо за ваш заказ! Вы можете скачать ваш файл, перейдя по следующей ссылке:';     } else {         echo 'Спасибо за ваш заказ! Вы выбрали ' . $total_quantity . ' товаров. ';         generate_archive_link($items); // Вызываем функцию для создания ссылки на архив     }      echo '</p>';      // Выводим количество товаров     echo '<p>Количество товаров: ' . $total_quantity . '</p>';      // Получение случайного товара     $random_item = reset($items);      // Получение товара     $product = $random_item->get_product();      // Получение файлов для товара     $files = $product->get_files();      // Если есть файлы, создаем ссылку для скачивания     if ($files) {         $file_data = reset($files);         $file_url = esc_url($file_data['file']);         $file_name = sanitize_file_name($file_data['name']); // Корректное имя файла          if ($total_quantity === 1) {             echo '<a id="download-link" href="' . $file_url . '" download="' . $file_name . '">' . $file_name . '</a>';         }          // Добавим JavaScript для отслеживания клика и отправки AJAX запроса         echo '<script>                 var countdown;                 var downloadLink = document.getElementById("download-link");                  downloadLink.addEventListener("click", function() {                     countdown = 10; // Устанавливаем время таймера                     updateCountdown();                     // Отправка AJAX запроса после клика                     var xhr = new XMLHttpRequest();                     xhr.open("POST", "' . admin_url('admin-ajax.php') . '", true);                     xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");                     xhr.send("action=update_downloadable_files&product_id=' . $product->get_id() . '&file_key=' . key($files) . '");                 });                  function updateCountdown() {                     if (countdown > 0) {                         downloadLink.innerHTML = "Файл будет загружен. Перенаправление на главную страницу через " + countdown + " секунд.";                         countdown--;                         setTimeout(updateCountdown, 1000);                     } else {                         window.location.href = "' . esc_url(home_url('/')) . '";                     }                 }               </script>';     } }  // AJAX обработчик для обновления списка файлов add_action('wp_ajax_update_downloadable_files', 'update_downloadable_files');  function update_downloadable_files() {     if (isset($_POST['product_id']) && isset($_POST['file_key'])) {         $product_id = intval($_POST['product_id']);         $file_key = sanitize_text_field($_POST['file_key']);          // Получаем файлы для товара         $product = wc_get_product($product_id);         $files = $product->get_files();          // Удаляем скачанный файл из списка         unset($files[$file_key]);          // Обновляем мета-данные товара         update_post_meta($product_id, '_downloadable_files', $files);     }      wp_die(); }

include_once('archive-function.php'); add_action('woocommerce_thankyou', 'customize_thank_you_page'); function customize_thank_you_page($order_id) { // Получение текущего заказа $order = wc_get_order($order_id); // Получение списка товаров в заказе $items = $order->get_items(); // Получение общего количества товаров в заказе $total_quantity = 0; // Вычисляем общее количество товаров foreach ($items as $item) { $total_quantity += $item->get_quantity(); } // Выводим информацию о товарах echo '<p>'; if ($total_quantity === 1) { echo 'Спасибо за ваш заказ! Вы можете скачать ваш файл, перейдя по следующей ссылке:'; } else { echo 'Спасибо за ваш заказ! Вы выбрали ' . $total_quantity . ' товаров. '; generate_archive_link($items); // Вызываем функцию для создания ссылки на архив } echo '</p>'; // Выводим количество товаров echo '<p>Количество товаров: ' . $total_quantity . '</p>'; // Получение случайного товара $random_item = reset($items); // Получение товара $product = $random_item->get_product(); // Получение файлов для товара $files = $product->get_files(); // Если есть файлы, создаем ссылку для скачивания if ($files) { $file_data = reset($files); $file_url = esc_url($file_data['file']); $file_name = sanitize_file_name($file_data['name']); // Корректное имя файла if ($total_quantity === 1) { echo '<a id="download-link" href="' . $file_url . '" download="' . $file_name . '">' . $file_name . '</a>'; } // Добавим JavaScript для отслеживания клика и отправки AJAX запроса echo '<script> var countdown; var downloadLink = document.getElementById("download-link"); downloadLink.addEventListener("click", function() { countdown = 10; // Устанавливаем время таймера updateCountdown(); // Отправка AJAX запроса после клика var xhr = new XMLHttpRequest(); xhr.open("POST", "' . admin_url('admin-ajax.php') . '", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("action=update_downloadable_files&product_id=' . $product->get_id() . '&file_key=' . key($files) . '"); }); function updateCountdown() { if (countdown > 0) { downloadLink.innerHTML = "Файл будет загружен. Перенаправление на главную страницу через " + countdown + " секунд."; countdown--; setTimeout(updateCountdown, 1000); } else { window.location.href = "' . esc_url(home_url('/')) . '"; } } </script>'; } } // AJAX обработчик для обновления списка файлов add_action('wp_ajax_update_downloadable_files', 'update_downloadable_files'); function update_downloadable_files() { if (isset($_POST['product_id']) && isset($_POST['file_key'])) { $product_id = intval($_POST['product_id']); $file_key = sanitize_text_field($_POST['file_key']); // Получаем файлы для товара $product = wc_get_product($product_id); $files = $product->get_files(); // Удаляем скачанный файл из списка unset($files[$file_key]); // Обновляем мета-данные товара update_post_meta($product_id, '_downloadable_files', $files); } wp_die(); }

Код из файла archive-function.php:

<?php  // Функция для создания ссылки на архив function generate_archive_link($items) {     // Получение случайного товара     $random_item = reset($items);      // Получение товара     $product = $random_item->get_product();      // Получение файлов для товара     $files = $product->get_files();      // Если есть файлы, создаем ссылку на архив     if ($files && count($files) > 1) {         $archive_url = admin_url('admin-ajax.php?action=generate_download_archive&product_id=' . $product->get_id());         echo '<p>Для удобства, вы можете <a href="' . esc_url($archive_url) . '">скачать все файлы в одном архиве</a>.</p>';     } }  // AJAX обработчик для создания архива add_action('wp_ajax_generate_download_archive', 'generate_download_archive');  function generate_download_archive() {     if (isset($_GET['product_id'])) {         $product_id = intval($_GET['product_id']);         $product = wc_get_product($product_id);         $files = $product->get_files();          if ($files) {             $zip = new ZipArchive();             $zip_filename = 'download_archive_' . $product_id . '.zip';              if ($zip->open($zip_filename, ZipArchive::CREATE)) {                 foreach ($files as $file_key => $file_data) {                     $file_url = WP_CONTENT_DIR . '/uploads/' . $file_data['file'];                     $zip->addFile($file_url, $file_data['name']);                 }                  $zip->close();                  header('Content-Type: application/zip');                 header('Content-Disposition: attachment; filename=' . $zip_filename);                 header('Content-Length: ' . filesize($zip_filename));                 readfile($zip_filename);                  // Удаляем архив после отправки                 unlink($zip_filename);                  exit();             }         }     }      wp_die(); }  ?>

<?php // Функция для создания ссылки на архив function generate_archive_link($items) { // Получение случайного товара $random_item = reset($items); // Получение товара $product = $random_item->get_product(); // Получение файлов для товара $files = $product->get_files(); // Если есть файлы, создаем ссылку на архив if ($files && count($files) > 1) { $archive_url = admin_url('admin-ajax.php?action=generate_download_archive&product_id=' . $product->get_id()); echo '<p>Для удобства, вы можете <a href="' . esc_url($archive_url) . '">скачать все файлы в одном архиве</a>.</p>'; } } // AJAX обработчик для создания архива add_action('wp_ajax_generate_download_archive', 'generate_download_archive'); function generate_download_archive() { if (isset($_GET['product_id'])) { $product_id = intval($_GET['product_id']); $product = wc_get_product($product_id); $files = $product->get_files(); if ($files) { $zip = new ZipArchive(); $zip_filename = 'download_archive_' . $product_id . '.zip'; if ($zip->open($zip_filename, ZipArchive::CREATE)) { foreach ($files as $file_key => $file_data) { $file_url = WP_CONTENT_DIR . '/uploads/' . $file_data['file']; $zip->addFile($file_url, $file_data['name']); } $zip->close(); header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename=' . $zip_filename); header('Content-Length: ' . filesize($zip_filename)); readfile($zip_filename); // Удаляем архив после отправки unlink($zip_filename); exit(); } } } wp_die(); } ?>

Помогите пожалуйста
Вот сайт на котором я это и делаю: https://atq-store.com/
Нажимайте на сам товар, а не на кнопку купить

Дополнительно:

Для начала оформите код через кнопку на форме </>
Включите вывод ошибок, может у вас zip расширение не стоит или ещё чего

  • Дмитрий, попробую, спасибо
  • sherl221, чтоб ссылкой был, не получится, у вас архив генерируется на лету, и отдаётся в арбузер на загрузку по аякс походу. Читайте логи пхп. Error.log
    Для отладки закоментируйте эти строки
    header('Content-Type: application/zip');                 header('Content-Disposition: attachment; filename=' . $zip_filename);                 header('Content-Length: ' . filesize($zip_filename));                 readfile($zip_filename);                  // Удаляем архив после отправки                 unlink($zip_filename);                  exit();

    header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename=' . $zip_filename); header('Content-Length: ' . filesize($zip_filename)); readfile($zip_filename); // Удаляем архив после отправки unlink($zip_filename); exit();

    Посмотрите архив. Если он весит мало, откройте его как текстовый и почитайте текст ошибки

  • Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Никита Орлов Ответ

    Пустой или повреждённый ZIP в WooCommerce чаще всего получается из-за неправильных путей к файлам, создания архива до того, как файлы реально найдены, отсутствия прав на запись или вывода лишнего HTML/пробелов в поток скачивания. Для цифровых товаров лучше сначала собрать реальные абсолютные пути к файлам, проверить их через file_exists(), а уже потом добавлять в ZipArchive.

    Базовая схема:

    $upload = wp_upload_dir();
    $zip_dir = trailingslashit($upload['basedir']) . 'order-zips/';
    wp_mkdir_p($zip_dir);
     
    $zip_path = $zip_dir . 'order-' . absint($order_id) . '.zip';
     
    $zip = new ZipArchive();
    if ($zip-&gt;open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        return;
    }
     
    foreach ($files as $file_path) {
        if (!file_exists($file_path)) {
            continue;
        }
     
        $zip-&gt;addFile($file_path, basename($file_path));
    }
     
    $zip-&gt;close();

    $upload = wp_upload_dir(); $zip_dir = trailingslashit($upload['basedir']) . 'order-zips/'; wp_mkdir_p($zip_dir); $zip_path = $zip_dir . 'order-' . absint($order_id) . '.zip'; $zip = new ZipArchive(); if ($zip-&gt;open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { return; } foreach ($files as $file_path) { if (!file_exists($file_path)) { continue; } $zip-&gt;addFile($file_path, basename($file_path)); } $zip-&gt;close();

    После close() проверьте размер:

    if (!file_exists($zip_path) || filesize($zip_path) === 0) {
        // логировать ошибку
    }

    if (!file_exists($zip_path) || filesize($zip_path) === 0) { // логировать ошибку }

    Не используйте URL файла там, где нужен путь на диске. ZipArchive::addFile() принимает именно локальный путь вроде /home/site/public_html/wp-content/uploads/file.txt, а не https://site.ru/wp-content/uploads/file.txt.

    Если архив создаётся на странице “Спасибо”, не выводите его напрямую в этот же момент. Лучше создать ZIP, сохранить его во временную папку uploads и вывести ссылку. Для безопасности ссылку нужно ограничить: проверять order key, пользователя или использовать signed URL.

    Итог: проверьте абсолютные пути, права на папку, результат $zip->open(), количество добавленных файлов и размер архива после закрытия. Почти всегда ошибка находится именно там.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно