Mam trochę kodu PHP, który uruchamia zapytanie w bazie danych, zapisuje wyniki w pliku csv, a następnie pozwala użytkownikowi pobrać plik. Problem polega na tym, że plik csv zawiera HTML strony wokół rzeczywistej zawartości CSV.Wymuszanie pobierania pliku w PHP - wewnątrz struktury Joomla
Przeczytałem wszystkie powiązane pytania już tutaj, w tym this one. Niestety mój kod istnieje w Joomla, więc nawet jeśli spróbuję przekierować na stronę zawierającą tylko nagłówki, Joomla automatycznie otacza ją swoim własnym kodem nawigacyjnym. Dzieje się tak tylko w momencie pobierania; jeśli spojrzę na plik csv, który jest zapisany na serwerze, nie zawiera kodu HTML.
Czy ktoś może mi pomóc w sposób wymuszający pobranie rzeczywistego pliku csv, tak jak to jest na serwerze, a nie jak jest to edytowane przez przeglądarkę? Próbowałem przy użyciu lokalizacji nagłówka, tak:
header('Location: ' . $filename);
ale otwiera plik w przeglądarce, raczej niż zmuszając zapisać okno.
Oto mój bieżący kod:
//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;
edytuje Pełny URL wygląda następująco:
http://mysite.com/administrator/index.php?option=com_eimcart&task=customers
z rzeczywistą odnośnik pobierania wygląda tak:
http://mysite.com/administrator/index.php?option=com_eimcart&task=customers&subtask=export
MOR E EDITS Oto ujęcie strony, na której jest kod; wygenerowany plik wciąż pobiera w html podmenu. Kod dla wybranego łącza (Eksportuj jako CSV) jest teraz
index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Teraz tutaj jest zrzut ekranu z wygenerowanym, zapisanego pliku:
To skurczyła się podczas przesłać tutaj, ale tekst podświetlony na żółto to kod html dla subnav (lista klientów, dodaj nowego klienta, eksportuj jako csv). Oto, jak wygląda teraz mój kompletny kod; gdybym mógł po prostu pozbyć się tego ostatniego fragmentu html, byłoby idealnie.
$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);
Aktualizacja dla Bjorn
Oto kod (chyba), który pracował dla mnie. Użyj RAW param w linku, który wywołuje działanie:
index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Ponieważ był proceduralny, nasz związek był w pliku o nazwie customers.php, który wygląda tak:
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;
}
więc gdy użytkownik kliknął powyższy link, plik export_csv.php jest automatycznie dołączany.Ten plik zawiera cały aktualny kod:
<?
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);
Prawdopodobnie konieczne będzie wyłączenie przepisywania adresu URL Joomla dla tego konkretnego przypadku. Czy możesz pokazać pełne adresy URL i plik .htaccess? –
Edytowanie OP w celu uwzględnienia żądanych informacji. – EmmyS
Ahh okay, to jest inaczej: Joomla prawdopodobnie slapuje nagłówek/stopkę na wyjściu w pliku indeksu, nie można tego naprawić przez dodanie reguły w .htaccess ... Wymaga eksperta od Joomla do uporządkowania –