Принудительная загрузка файлов в PHP - внутри фреймворка Joomla

У меня есть некоторый код PHP, который выполняет запрос к базе данных, сохраняет результаты в CSV-файл, а затем позволяет пользователю загрузить файл. Проблема в том, что файл CSV содержит страницу HTML вокруг фактического содержимого CSV.

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

Может кто-нибудь помочь мне с помощью способа принудительной загрузки фактического файла CSV, как он есть на сервере, а не так, как браузер редактирует его, чтобы быть? Я попытался использовать местоположение заголовка, как это:

header('Location: ' . $filename);

но он открывает файл в браузере, а не форсирует диалог сохранения.

Вот мой текущий код:

//set dynamic filename
$filename = "customers.csv";
//open file to write csv
$fp = fopen($filename, 'w');

//get all data
$query = "select 
   c.firstname,c.lastname,c.email as customer_email, 
   a.email as address_email,c.phone as customer_phone,
   a.phone as address_phone,
   a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin
   from {$dbpre}customers c
   left  join  {$dbpre}customers_addresses a  on c.id = a.customer_id  order by c.last_signin desc";

$votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
$counter = 1;
while ($row = mysql_fetch_array($votes,1)) {
    //put header row
    if ($counter == 1){
       $headerRow = array();
       foreach ($row as $key => $val)
          $headerRow[] = $key;
       fputcsv($fp, $headerRow);
    }
    //put data row
    fputcsv($fp, $row);
    $counter++;
}

//close file
fclose($fp);

//redirect to file
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Transfer-Encoding: binary");
readfile($filename); 
exit;

редактирует Полный URL выглядит так:

http://mysite.com/administrator/index.php?option=com_eimcart&task=customers

с реальной ссылкой для скачивания, похожей на это:

http://mysite.com/administrator/index.php?option=com_eimcart&task=customers&subtask=export

БОЛЬШЕ РЕДАКТИРОВАТЬ Вот снимок страницы, на которой находится код; сгенерированный файл все еще загружает HTML-файл для подменю. Код для выбранной ссылки (Экспорт в CSV) теперь

index.php?option=com_eimcart&task=customers&subtask=export&format=raw

Теперь вот скриншот сгенерированного, сохраненного файла:

Он сократился во время загрузки здесь, но текст, выделенный желтым цветом, является html-кодом для subnav (список клиентов, добавление нового клиента, экспорт в формате csv). Вот как теперь выглядит мой полный код; если бы я мог просто избавиться от этой последней части HTML, это было бы прекрасно.

  $fp= fopen("php://output", 'w');

            $query = "select c.firstname,c.lastname,c.email as customer_email, 
                      a.email as address_email,c.phone as customer_phone,
                      a.phone as address_phone,  a.company, a.address1,
                      a.address2,a.city,a.state,a.zip,c.last_signin

                      from {$dbpre}customers c
                      left  join  {$dbpre}customers_addresses a on c.id = a.customer_id  
                      order by c.last_signin desc";

            $votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
            $counter = 1;

            //redirect to file
            header("Content-type: application/octet-stream");
            header("Content-Disposition: attachment; filename=customers.csv");
             header("Content-Transfer-Encoding: binary");

            while ($row = mysql_fetch_array($votes,1)) {

                    //put header row
                    if ($counter == 1){
                            $headerRow = array();
                            foreach ($row as $key => $val)
                                    $headerRow[] = $key;

                            fputcsv($fp, $headerRow);
                    }

                    //put data row
                    fputcsv($fp, $row);
                $counter++;
            }

            //close file
            fclose($fp);

ОБНОВЛЕНИЕ ДЛЯ BJORN

Вот код (я думаю), который работал для меня. Используйте параметр RAW в ссылке, которая вызывает действие:

index.php?option=com_eimcart&task=customers&subtask=export&format=raw

Поскольку это было процедурно, наша ссылка была в файле Customers.php, который выглядит следующим образом:

switch ($r['subtask']){
    case 'add':
    case 'edit':
        //if the form is submitted then go to validation
                include("subnav.php");
        if ($r['custFormSubmitted'] == "true")
            include("validate.php");
        else
            include("showForm.php");
        break;

    case 'delete':
                include("subnav.php");
        include("process.php");
            break;

    case 'resetpass':
                include("subnav.php");
        include("resetpassword");
            break;

    case 'export':
        include("export_csv.php");
            break;


    default:
                include("subnav.php");
        include("list.php");
        break;
}

Поэтому, когда пользователь нажимает на ссылку выше, файл export_csv.php автоматически включается. Этот файл содержит весь фактический код:

<?
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=customers.csv");
header("Content-Transfer-Encoding: binary");
$fp= fopen("php://output", 'w');


//get all data
$query = "select 
    c.firstname,c.lastname,c.email as customer_email, 
    a.email as address_email,c.phone as customer_phone,
    a.phone as address_phone,
    a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin

    from {$dbpre}customers c

    left  join  {$dbpre}customers_addresses a  on c.id = a.customer_id  order by c.last_signin desc";


$votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
$counter = 1;

while ($row = mysql_fetch_array($votes,1)) {

    //put header row
    if ($counter == 1){
        $headerRow = array();
        foreach ($row as $key => $val)
            $headerRow[] = $key;

        fputcsv($fp, $headerRow);
    }

    //put data row
    fputcsv($fp, $row);
    $counter++;
}

//close file
fclose($fp);

Ответы на вопрос(4)

Ваш ответ на вопрос