Tengo un código PHP que ejecuta una consulta en una base de datos, guarda los resultados en un archivo csv, y luego le permite al usuario descargar el archivo. El problema es que el archivo csv contiene páginas HTML alrededor del contenido csv real.Forzando la descarga de archivos en PHP - dentro de Joomla framework
He leído todas las preguntas relacionadas aquí, incluyendo this one. Lamentablemente, mi código existe en Joomla, por lo que incluso si trato de redireccionar a una página que no contiene más que encabezados, Joomla automáticamente lo rodea con su propio código de navegación. Esto solo ocurre en el momento de la descarga; si miro el archivo csv que está guardado en el servidor, no contiene el HTML.
¿Alguien puede ayudarme con una forma de forzar una descarga del archivo csv real tal como está en el servidor, en lugar de como lo está editando el navegador? He intentado usar la ubicación de cabecera, así:
header('Location: ' . $filename);
pero se abre el archivo en el navegador, en lugar de forzar el diálogo Guardar.
Aquí está mi código actual:
//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;
EDITS URL completa se ve así:
http://mysite.com/administrator/index.php?option=com_eimcart&task=customers
con el enlace de descarga real con este aspecto:
http://mysite.com/administrator/index.php?option=com_eimcart&task=customers&subtask=export
MOR E EDICIONES Aquí hay una foto de la página en la que se encuentra el código; el archivo generado todavía está tirando en el html para el submenú. El código para el enlace seleccionado (Exportar como CSV) es ahora
index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Ahora aquí está una captura de pantalla del archivo generado, guardada:
Se redujo durante el cargue aquí, pero el texto resaltado en amarillo es el código html para el subnav (enumere clientes, agregue nuevos clientes, exporte como csv). Así es como se ve mi código completo ahora; si pudiera deshacerme de ese último bit de html, sería perfecto.
$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);
ACTUALIZACIÓN Björn
Aquí está el código (creo) que trabajó para mí. Utilizar el parámetro RAW en el enlace que llama a la acción:
index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Debido a que este era de procedimiento, era nuestro enlace en un archivo llamado clientes.php, que se ve así:
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;
}
Así que cuando una usuario hizo clic en el enlace de arriba, el archivo export_csv.php se incluye automáticamente.Ese archivo contiene todo el código real:
<?
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);
Probablemente necesite desactivar la reescritura de URL de Joomla para este caso específico. ¿Puedes mostrar algunas URL completas y tu archivo .htaccess? –
Editando OP para incluir la información solicitada. – EmmyS
Ahh bien, eso es diferente: Joomla probablemente golpea el encabezado/pie de página en la salida en el archivo de índice, esto no se puede arreglar agregando una regla en .htaccess ... Necesita un experto en Joomla para resolver –