Tengo un enlace que va a un script PHP que genera un archivo CSV para descargar y guardar. Genero los encabezados Content-Disposition y Content-Type en la respuesta. Cada navegador descarga el archivo bien excepto para Chrome (v19).Chrome está malinterpretando un archivo adjunto como documento
El enlace es algo como esto:
http://hostname.com/controller/action/export
Las cabeceras regresaron de esa solicitud son:
Cache-control:no-cache, must-revalidate
Connection:Keep-Alive
Content-Disposition:attachment; filename=2012-03-14.csv
Content-Encoding:gzip
Content-Length:521
Content-Type:application/vnd.ms-excel
Date:Thu, 15 Mar 2012 05:17:55 GMT
Expires:Mon, 26 Jul 1997 05:00:00 GMT
Keep-Alive:timeout=5, max=92
P3P:CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Pragma:no-cache
Server:Apache/2.2.11 (Win32) mod_ssl/2.2.11 OpenSSL/0.9.8i mod_autoindex_color PHP/5.2.9
Vary:Accept-Encoding
X-Powered-By:PHP/5.2.9
Los desarrolladores de herramientas de Chrome muestra que la conexión de red fue Canceled
y la ventana de la consola muestra el siguiente error:
Resource interpreted as Document but transferred with MIME type application/vnd.ms-excel:
He intentado utilizar diferentes valores para Content-Type, he desactivado los encabezados Cache-Control y Content-Type. He probado utilizando Javascript location.href=
, una etiqueta <a>
, <form action="POST">
, he desactivado la compresión Gzip y varios otros métodos para intentar que Chrome descargue realmente el archivo.
Cualquier otro navegador descarga bien el archivo, por lo que mi pregunta es: ¿Qué hace que Chrome interprete la solicitud como un "Documento" para mostrar en lugar de un archivo adjunto? ¿Hay otro encabezado que me falta o un encabezado en la lista que lo confunde?
EDIT: Aquí está el código PHP a lo solicitado, aunque es un poco largo:
function renderHeaders($filename = null) {
header("Content-Type: application/vnd.ms-excel");
header("Cache-Control: public, must-revalidate, max-age=0");
if (is_string($filename)) {
$this->setFilename($filename);
}
if ($this->filename === null) {
$this->filename = 'Data.csv';
}
if ($this->filename) {
header("Content-disposition: attachment; filename=".$this->filename);
}
}
function render($outputHeaders = true, $to_encoding = null, $from_encoding = "auto") {
if ($outputHeaders) {
$this->renderHeaders();
}
if ($this->_tmpFile) {
rewind($this->buffer);
$output = '';
while (!feof($this->buffer)) {
$output .= fread($this->buffer, 8192);
}
fclose($this->buffer);
} else {
rewind($this->buffer);
$output = stream_get_contents($this->buffer);
}
// get around excel bug (http://support.microsoft.com/kb/323626/)
if (substr($output,0,2) == 'ID') {
$pos = strpos($output, $this->delimiter);
if ($pos === false) {
$pos = strpos($output, "\n");
}
if ($pos !== false) {
$output = $this->enclosure . substr($output, 0, $pos) . $this->enclosure . substr($output, $pos);
}
}
if ($to_encoding) {
$output = mb_convert_encoding($output, $to_encoding, $from_encoding);
}
$this->clear();
return $this->output($output);
}
Se puede publicar su código php que genera las cabeceras –
Creo que es posible que desee presentar un insecto) –
no estoy seguro de si haría cualquier diferencia, pero ¿qué pasa con el envío de 'Content-Transfer-Encoding: Binary'? –