PHP экспортирует несколько файлов excel

Я пытаюсь экспортировать несколько таблиц из базы данных и создаю файл excel для каждой таблицы с помощью PHP. Однако петля «прослушивается». Вместо того, чтобы создавать новый файл для каждого цикла, он просто помещает все данные в один и тот же файл.

Код:

  foreach ($pdo->query("SHOW TABLES;") as $allTables) {
    $table = $allTables[0];

    $allDataStmt = $pdo->prepare("SELECT * FROM $table;");
    $allDataStmt->execute();

    $fieldcount = $allDataStmt->columnCount();

    $col_title = "";
    $data = "";
    for ($i = 0; $i < $fieldcount; $i++) {
      $col = $allDataStmt->getColumnMeta($i);
      $column = $col['name'];
      $col_title .= '<Cell ss:StyleID = "2"><Data ss:Type = "String">' . $column . '</Data></Cell>';
    }

    $col_title = '<Row>' . $col_title . '</Row>';

    while ($row = $allDataStmt->fetch(PDO::FETCH_NUM)) {
      $line = '';
      foreach ($row as $value) {
        if ((!isset($value)) or ($value == "")) {
          $value = '<Cell ss:StyleID = "1"><Data ss:Type = "String"></Data></Cell>\t';
        } else {
          $value = str_replace('"', '', $value);
          $value = '<Cell ss:StyleID = "1"><Data ss:Type = "String">' . $value . '</Data></Cell>\t';
        }
        $line .= $value;
      }
      $data .= trim("<Row>" . $line . "</Row>") . "\n";
    }

    $data = str_replace("\r", "", $data);

    header("Content-Type: application/vnd.ms-excel;");
    header("Content-Disposition: attachment; filename = " . $table . ".xls");
    header("Pragma: no-cache");
    header("Expires: 0");
  }
}

Если я остановлю цикл после первой итерации, он правильно экспортирует данные из ОДНОЙ таблицы. Если я позволю циклу запуститься, он просто загрузит тот же файл с данными, и файл будет поврежден. Я даже не могу открыть его в Excel.

Что мне не хватает? Застрял с этим в течение нескольких часов.

Благодарю вас!

Случайно ли ваша переменная $table продолжает обращаться к первому индексу массива в $allTables[0]? Возможно, вам нужна переменная счетчика/индекса, чтобы она не ссылалась на один и тот же экземпляр?

Max Voisard 03.05.2022 01:22

@MaxVoisard Я тоже об этом думал, но когда я распечатываю таблицы и только таблицы, они распечатываются правильно. Они появляются не более одного раза. Надеюсь, я правильно понял, что вы имеете в виду.

leo 03.05.2022 01:25

После некоторых исследований я обнаружил, что то, что вы пытаетесь сделать, невозможно для одного HTTP-запроса, и лучшим решением является добавление в файл .zip. Проверьте мой ответ.

Max Voisard 03.05.2022 02:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

То, что вы пытаетесь сделать с несколькими разными вложениями в одном и том же HTTP-запросе, невозможно. Протокол HTTP не поддерживает загрузку нескольких файлов. Самый распространенный обходной путь — поместить файлы в zip-архив для загрузки клиентом, например:

$zip = new ZipArchive;
$zip_name = "excel_tables.zip";

if ($zip->open($zip_name, ZipArchive::CREATE|ZipArchive::OVERWRITE) === TRUE) {
    foreach ($pdo->query("SHOW TABLES;") as $allTables) {
        // (Your logic to build Excel file)

        $file_content = $col_title . "\n" . $data;

        $file_name = $table . ".xls";
        file_put_contents($file_name, $file_content);

        // Add file to the zip file
        $zip->addFile($file_name);
    }

    $zip->close();
    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename=' . $zip_name);
    header("Content-Length: " . filesize($zip_name));
    header("Pragma: no-cache"); 
    header("Expires: 0"); 
    ob_clean();
    flush();
    readfile(__DIR__ . "/" . $zip_name);
}

вау еще лучше. Благодарю вас! На самом деле это было то, что я планировал сделать после исправления этой проблемы, ха-ха. Я попробовал это сейчас, но продолжаю получать эту ошибку: Предупреждение: ZipArchive::addFile(): Нет такого файла или каталога в xxxxx

leo 03.05.2022 02:40

Смотрите мое редактирование - похоже, что корневой путь сервера должен быть включен для расположения zip-файла. Я также отредактировал метод open(), чтобы он был заключен в условие, которое перезаписывает тот же самый zip-файл, а не создает его. Не уверен, но надеюсь, что это сработает.

Max Voisard 03.05.2022 02:44

к сожалению, я продолжаю получать ту же ошибку. Если я использую это условие, которое вы добавили, вообще ничего не происходит. Если я не использую его, я получаю ту же ошибку, что и раньше.

leo 03.05.2022 02:58

Вы изменили переменную $zip_name, чтобы включить корень сервера?

Max Voisard 03.05.2022 03:01

да. $zip_name = $_SERVER['DOCUMENT_ROOT'] . "/excel_tables.zip";

leo 03.05.2022 03:07

Я понимаю, что проблема была не в пути сервера к zip-файлу, а в попытке добавить несуществующий файл. Вы когда-нибудь добавляли созданное вами содержимое в файл Excel, например, через переменные $col_title и $data, а затем отправляли его на сервер? Я не вижу этого в вашем коде. Я отредактировал свой ответ на случай, если это то, чего не хватает.

Max Voisard 03.05.2022 03:55

Макс, ты находка, теперь все работает. файлы записываются в zip-архив. Большое спасибо! Можно ли как-то загрузить zip-файл от имени пользователя? Я имею в виду, если кто-то нажмет «Загрузить», он будет сохранен на его / ее компьютере?

leo 03.05.2022 04:09

Пожалуйста, и приятно слышать, что это работает - что касается вашего вопроса, вы имеете в виду, что zip-файл просто загружается одним нажатием кнопки? Если это так, то да, вам просто нужно вызвать этот код при отправке формы.

Max Voisard 03.05.2022 04:15

Да, точно. Ну, это не работает. Файлы скачиваются в папку, указанную в коде. Но он не загружается в папку «Загрузки» на моем ПК.

leo 03.05.2022 04:17

Может быть несколько отсутствующих заголовков, необходимых для загрузки zip-архива на компьютер клиента. Проверьте обновленный ответ.

Max Voisard 03.05.2022 04:24

до сих пор не работает. Это странно, потому что я использовал точно такие же заголовки ранее, и он начал загрузку, когда я делал отдельные файлы. Странно, как он не загружается сейчас с теми же заголовками, ха-ха.

leo 03.05.2022 04:29

Судя по документам, которые я только что прочитал, везде, где zip-файл загружается на сервер, вы должны указать этот путь перед методом readfile(). Смотрите мое редактирование — если «ДИР» не работает, просто используйте текущий рабочий каталог, в котором находится код.

Max Voisard 03.05.2022 04:43

все еще не работает, к сожалению. Я посмотрю подробнее завтра. На данный момент здесь 5 утра, и я делаю это уже более 10 часов. Я очень ценю вашу помощь и ваше время! Ты меня проделал долгий путь. Большое спасибо еще раз!

leo 03.05.2022 04:56

Я решил это. Я что-то распечатывал в цикле foreach, из-за чего он не загружался. Теперь все работает нормально!

leo 03.05.2022 05:09

Хорошо, приятно слышать, что он загружается.

Max Voisard 03.05.2022 16:13

Другие вопросы по теме