Я столкнулся с довольно интересной (и разочаровывающей) проблемой с IE6. Мы обслуживаем некоторые серверные pdf-файлы, а затем просто устанавливаем заголовки в PHP, чтобы заставить браузер загружать файл. Работает нормально и все, кроме IE6, но только если учетная запись пользователя Windows установлена на стандартного пользователя (то есть не на администратора).
Поскольку это для корпоративной среды, конечно, все их учетные записи настроены таким образом. Странно, что в диалоговом окне загрузки Content-Type не распознается:
header( 'Pragma: public' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' ); header( 'Cache-Control: public' ); header( 'Content-Description: File Transfer' ); header( 'Content-Type: application/pdf' ); header( 'Content-Disposition: attachment; filename="xxx.pdf"' ); header( 'Content-Transfer-Encoding: binary' ); echo $content; exit;
Я также попытался сначала записать содержимое файла во временный файл, чтобы я мог также установить Content-Length
в заголовке, но это не помогло.
Content-Transfer-Encoding: binary
Этот заголовок скопирован из заголовков электронной почты. Это не относится к HTTP просто потому, что HTTP не имеет другого способа передачи, кроме двоичного. Установка его имеет такой же смысл, как установка X-Bits-Per-Byte: 8
.
Cache-control: pre-check=0, post-check=0
Эти нестандартные значения определяют, когда IE должен проверить, остается ли кешированный контент еще свежим. 0
является значением по умолчанию, поэтому установка его в 0
является пустой тратой времени. Эти директивы применяются только к кешируемому контенту и Expires:0
и must-revalidate
намекать, что вы хотите сделать его не кэшируемым.
Content-Description: File Transfer
Это еще один подкаталог электронной почты. По дизайну этот заголовок никак не влияет на загрузку . Это просто информативный текст свободной формы. Это технически так же полезно, как X-Hi-Mom: I'm sending you a file!
заголовок.
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' ); header( 'Cache-Control: public' );
В PHP вторая строка полностью перезаписывает первый. Кажется, вы вздрагиваете в темноте.
Content-Disposition: attachment
Вам не нужно вставлять туда имя файла (вы можете использовать mod_rewrite
или index.php/fakefilename.doc
trick – он дает гораздо лучшую поддержку специальных символов и работает в браузерах, которые игнорируют дополнительный заголовок Content-Disposition
).
В IE имеет значение, находится ли файл в кеше или нет («Открыть» не работает для файлов, не относящихся к кешированию), и есть ли у пользователя плагин, который утверждает, что поддерживает тип файла, который обнаруживает IE.
Чтобы отключить кеш, вам нужен только Cache-control:no-cache
(без 20 дополнительных поддельных заголовков), а для кэширования файлов вам нечего отправлять.
NB: PHP имеет ужасную ошибку, называемую session.cache_limiter
которая безнадежно закручивает HTTP-заголовки, если вы не установите ее на none
.
ini_set('session.cache_limiter','none'); // tell PHP to stop screwing up HTTP
некоторые версии IE, похоже,
header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
слишком серьезно, и удалить загруженный контент, прежде чем он будет передан плагину для его отображения.
Удалите эти два, и вы должны быть в порядке.
И убедитесь, что вы не используете сжатие GZIP на стороне сервера при работе с PDF-файлами, потому что некоторые версии Acrobat, похоже, борются с этим.
Я знаю, что я расплывчатый, но выше советы основаны на реальном опыте, я получил использование веб-приложения, обслуживающего динамически построенные PDF-файлы, содержащие штрих-коды. Я не знаю, какие версии затронуты, я только знаю, что использование двух «трюков» выше заставило звонки поддержки уйти: p
У меня была такая же проблема примерно год назад, и после многого поиска и исследований мои заголовки (из Java-кода) ищут IE6 и PDF-файлы:
response.setHeader("Content-Type", "application/pdf "; name=" + file.getName()); response.setContentType("application/pdf"); response.setHeader("Last-Modified", getHeaderDate(file.getFile()); response.setHeader("Content-Length", file.getLength());
Брось все.
По-видимому, что-то немного странное с IE6, кэширование, принудительная загрузка и плагины. Я надеюсь, что это сработает для вас … Небольшая разница для меня заключается в том, что запрос изначально происходит из файла SWF Flash. Но это не имеет значения.
Я ценю время, которое вы, ребята, потратили на этот пост. Я попробовал несколько комбинаций и, наконец, получил свой проект symfony. Здесь я публикую решения, если у кого-то будет такая же проблема:
public function download(sfResponse $response) { $response->clearHttpHeaders(); $response->setHttpHeader('Pragma: public', true); $response->addCacheControlHttpHeader("Cache-control","private"); $response->setContentType('application/octet-stream', true); $response->setHttpHeader('Content-Length', filesize(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename()), true); $response->setHttpHeader("Content-Disposition", "attachment; filename=\"". $this->getFilename() ."\""); $response->setHttpHeader('Content-Transfer-Encoding', 'binary', true); $response->setHttpHeader("Content-Description","File Transfer"); $response->sendHttpHeaders(); $response->setContent(readfile(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename())); return sfView::NONE; }
Это отлично работает для меня в IE6, IE7, Chrome, Firefox.
Надеюсь, это поможет кому-то.
Как уже упоминал пилиф, обязательно отключите сжатие gzip на стороне сервера. Для меня это вызвало проблемы с файлами PDF (среди других типов) и, возможно, с неясными причинами и с .zip-файлами как в Internet Explorer, так и в FireFox.
Насколько я мог судить, последний бит нижнего колонтитула будет раздет (по крайней мере, FireFox), что приведет к повреждению формата.
В PHP вы можете использовать следующий код:
ini_set("zlib.output_compression",0);
Следующий бит Java-кода работает для меня (тестируется на Firefox 2 и 3, IE 6 и 7):
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); response.setContentType(getServletContext().getMimeType(file.getName())); response.setContentLength(file.length());
Никаких других заголовков не было вообще. Кроме того, я тестировал этот код как с включением и выключением сжатия gzip (используя отдельный фильтр сервлета, который выполняет сжатие). Не имеет значения (работает без проблем в четырех браузерах, на которых я тестировал). Кроме того, это работает и для других типов файлов.
Вы можете добавить дополнительный параметр, который сервер не будет читать на URL-адресе, который может помочь.
http://www.mycom.com/services/pdf?action=blahblah&filename=pdf0001.pdf
Я столкнулся с случаями, когда, например, будет более вероятно читать имя файла в конце URL-адреса, чем любой из заголовков
У меня была аналогичная проблема, но она не может быть точно связана. Моя проблема заключалась в том, что IE6, похоже, имеет проблемы со специальными символами (в частности, слэши) в имени файла. Удаление этих исправлено.
Если вы используете SSL:
Убедитесь, что вы не включаете заголовки кеша (или Pragma). В IE6 есть ошибка, которая не позволит пользователям загружать файлы, если используются заголовки управления кешем. Они получат сообщение об ошибке.
Я вытащил свои волосы за это в течение 2 дней, поэтому, надеюсь, это сообщение помогает кому-то.
просто переключитесь на этот тип контента, и он будет работать, также убедитесь, что Pragma ist установлен на что-то НЕ равное "no-cache"
header( 'Content-type: application/octet-stream'); # force download, no matter what mimetype header( 'Content-Transfer-Encoding: binary' ); # is always ok, also for plain text