Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome is misinterpreting a file attachment as a document

I have a link that goes to a PHP script that generates a CSV file to be downloaded and saved. I generate the Content-Disposition and Content-Type headers in the response. Every browser downloads the file fine except for Chrome (v19).

The link is something like this:

http://hostname.com/controller/action/export

The headers returned from that request are:

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

The Chrome developers tools shows that the network connection was Canceled and the console window shows the following error:

Resource interpreted as Document but transferred with MIME type application/vnd.ms-excel:

I have tried using different values for Content-Type, I have turned off the Cache-Control and Content-Type headers. I have tested using Javascript location.href=, an <a> tag, a <form action="POST">, turned off Gzip compression, and various other methods to attempt to get Chrome to actually download the file.

Every other browser downloads the file fine, so my question is: What is causing Chrome to interpret the request as a "Document" for display instead of an attachment? Is there another header I'm missing or a header in the list that's confusing it?

EDIT: Here's the PHP code as requested, though it's a bit long:

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);
}
like image 655
Chris Thompson Avatar asked Mar 15 '12 05:03

Chris Thompson


1 Answers

The content type is wrong, it should be text/csv, not application/vnd.ms-excel.

Source: Wikipedia

like image 108
Eva Lauren Kelly Avatar answered Sep 23 '22 14:09

Eva Lauren Kelly