Chrome将文件附件误解为文档

时间:2012-03-15 05:28:11

标签: php http google-chrome

我有一个链接到PHP脚本,该脚本生成要下载和保存的CSV文件。我在响应中生成Content-Disposition和Content-Type标头。每个浏览器都会为Chrome(v19)下载之外的文件。

链接是这样的:

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

该请求返回的标头是:

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

Chrome开发人员工具显示网络连接为Canceled,控制台窗口显示以下错误:

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

我尝试过为Content-Type使用不同的值,我已经关闭了Cache-Control和Content-Type标头。我已使用Javascript location.href=<a>代码,<form action="POST">进行了测试,关闭了Gzip压缩,以及尝试让Chrome实际下载该文件的各种其他方法。

其他每个浏览器都能正常下载该文件,因此我的问题是:是什么原因导致Chrome将请求解释为“文档”以显示而不是附件?是否有其他标题我丢失或列表中的标题令人困惑?

编辑:这是所要求的PHP代码,虽然它有点长:

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);
}

4 个答案:

答案 0 :(得分:1)

内容类型有误,应该是text/csv,而不是application/vnd.ms-excel

来源:Wikipedia

答案 1 :(得分:0)

这是因为您的内容类型。

你应该改变: 内容类型:应用/ vnd.ms-Excel中

试试这个:

<?php

header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
...

答案 2 :(得分:0)

试试这个,它应该强制在所有浏览器上下载。

    header ("Content-type: octet/stream");
    header ("Content-disposition: attachment; filename=\"".$file."\";");
    header("Content-Length: ".filesize($file));
    readfile($file);

答案 3 :(得分:0)

&#39; application / vnd.ms-excel&#39; MIME类型专门用于Microsoft Excel二进制.xls文件。告诉你发送二进制文件然后将文本文件交给Chrome会导致问题。相反,请使用已批准的逗号分隔值类型&#39; application / csv&#39;。

替换:

header("Content-Type: application/vnd.ms-excel");

使用:

header("Content-Type: application/csv");