PHP: загрузка файла Force и IE, еще раз

Люди, я знаю, что было много потоков о том, чтобы заставить диалоговое окно загрузки всплывать, но ни одно из решений не помогло мне.

Мое приложение отправляет почту на учетную запись электронной почты пользователя, сообщая им, что "другой пользователь отправил им сообщение". Эти сообщения могут иметь ссылки на файлы Excel. Когда пользователь нажимает на ссылку в своей почте GMail/Yahoo Mail/Outlook на этот файл Excel, я хочу открыть диалоговое окно "Сохранить файл".

Проблема: когда я нажимаю правой кнопкой мыши и делаю "Сохранить как" в IE, я получаю диалог "Сохранить как". Когда я просто нажимаю ссылку (которую многие мои клиенты будут делать, поскольку они не сообразительны), я получаю сообщение об ошибке IE: "IE не может загрузить файл... из...". Может быть актуальным: на GMail, где я тестирую это, каждая ссылка является ссылкой "target = _blank" (принудительно с помощью Google).

Все остальные браузеры работают нормально во всех случаях.

Вот мои заголовки (захваченные через Fiddler):

HTTP/1.1 200 OK
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Content-Length: 15872
Via: **** // proxy server name
Expires: 0
Date: Tue, 20 Oct 2009 22:41:37 GMT
Content-Type: application/vnd.ms-excel
Server: Apache/2.2.11 (Unix) DAV/2 mod_ssl/2.2.11 OpenSSL/0.9.8i mod_python/3.3.1 Python/2.5.2 SVN/1.4.6 mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0
Cache-Control: private
Pragma: no-cache
Last-Modified: Tue, 20 Oct 2009 22:41:37 GMT
Content-Disposition: attachment; filename="myFile.xls"
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100

Я хочу, чтобы IE работал с обычным левым кликом. Есть идеи?

Ответ 1

Это будет проверять версии IE и соответственно устанавливать заголовки.

// assume you have a full path to file stored in $filename
if (!is_file($filename)) {
  die('The file appears to be invalid.');
}

$filepath = str_replace('\\', '/', realpath($filename));
$filesize = filesize($filepath);
$filename = substr(strrchr('/'.$filepath, '/'), 1);
$extension = strtolower(substr(strrchr($filepath, '.'), 1));

// use this unless you want to find the mime type based on extension
$mime = array('application/octet-stream');

header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.sprintf('%d', $filesize));
header('Expires: 0');

// check for IE only headers
if (preg_match('~MSIE|Internet Explorer~i', $_SERVER['HTTP_USER_AGENT']) || (strpos($_SERVER['HTTP_USER_AGENT'], 'Trident/7.0; rv:11.0') !== false)) {
  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  header('Pragma: public');
} else {
  header('Pragma: no-cache');
}

$handle = fopen($filepath, 'rb');
fpassthru($handle);
fclose($handle);

Ответ 2

Просто используйте:

header('Content-Disposition: attachment');

Это все. (Facebook делает то же самое.)

Ответ 3

Если вы пытаетесь каждый раз загружать файл, измените тип содержимого на "application/octet-stream".

Попробуйте это без инструкции pragma.