Ошибка браузера Android/веб-просмотра? Content-Disposition: вложение; имя файла=xyz.txt

Таким образом, браузер Android или веб-просмотр отлично работают с такими URL-адресами - abc.com/xyz.txt

Однако, если ваш URL-адрес выглядит так: abc.com/xyz.php, и то, что отправляется в браузер в заголовках, — Content-Disposition: вложение; filename="xyz.txt", то браузеры Android и веб-представление, кажется, ужасно запутались.

Похоже, он сохраняет правильное имя файла на телефоне, но содержимое заполнено веб-страницей, которая просматривалась ранее. Это прекрасно работает в браузерах на базе ПК, а также на iPhone и Blackberry, проблема возникает только на Android 2.1 и 2.2 (другие не тестировались).

У кого-нибудь есть решение? Буду очень признателен. Я на самом деле не хочу начинать хранить статические файлы и хочу создавать загружаемый контент на лету. Журнал на телефоне не выявил никаких зацепок.


Вот что сервер отправляет в браузер

===================== start content ====================================
HTTP/1.1 200 OK
Date: Thu, 21 Oct 2010 21:22:11 GMT
Server: Apache
Content-Disposition: attachment; filename="Wafty.txt"
Content-length: 30
Content-Type: text/plain; charset=ISO-8859-1

Hello this is a test of a file
========= There was no carriage return at the end of the above line ====

person Anil Pais    schedule 22.10.2010    source источник
comment
Создавайте загружаемый контент на лету, сохраняйте его во временном файле и выполняйте для него переадресацию 301. Очистите сгенерированный контент с помощью задания cron/запланированного задания. Это может быть неловко - это просто мысль.   -  person CommonsWare    schedule 22.10.2010
comment
@CommonsWare: это оскорбляет мои чувства! :-)   -  person Anil Pais    schedule 22.10.2010
comment
Попробуйте изменить Content-Type на application/octet-stream .   -  person clu3Less    schedule 05.11.2013


Ответы (2)


Использовать:

Content-Disposition: attachment;filename="xyz.txt"

Не используйте (учитывайте дополнительное пространство):

Content-Disposition: attachment;  filename="xyz.txt"
person user902411    schedule 29.08.2011
comment
У меня есть несколько веб-сервисов, и это пространство не представляет проблемы. Вот пример заголовка ответа: Content-Disposition: attachment; имя файла=test.txt - person Sal; 02.06.2017
comment
Я сделал еще несколько исправлений, кроме этого, но я думаю, что это была критическая часть, которая фактически устранила проблему! Спасибо! - person The Godfather; 21.10.2020

У меня похожая проблема с вашей. Проблема здесь в том, как WebView обрабатывает вложения (настоящая головная боль). Когда WebView посещает веб-страницу, которая в какой-то момент возвращает вложение, он говорит что-то вроде «О, дерьмо, что я могу сделать с этой не-HTML-штукой?… Эй, вы! DownloadListener! сделайте что-нибудь с этим URL, который говорит: какой-то бред про приставку». Итак, DownloadListener берет верх, и вот в чем проблема: он снова запрашивает тот же URL для загрузки вложения, поэтому для загрузки вложения при посещении страницы WebView выполняет 2 запроса: саму страницу, а затем еще один для загрузки вложение, а не просто скачать его.

И как это проблема? Ну, допустим, что в вашем abc.com/xyz.php у вас есть какая-то логика вроде:

<?php
   if(User::loggedIn()) {
       header("Content-Disposition: attachment...");
       //Some more logic for the download
   }
?>

Второй запрос, выполненный DownloadListener, сделает еще один запрос к abc.com/xyz.php, но на этот раз он не будет содержать файлы cookie или информацию о сеансе, поэтому он не войдет в логику «загрузки».

Возможным решением было бы перенаправление на временную копию или реальный путь к файлу, который не содержит никакой логики, поэтому проблем не возникает. Конечно, вам также необходимо определить прослушиватель загрузки в вашем веб-представлении, например, что-то вроде этого.

webView.setDownloadListener(new DownloadListener() {

    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {

        final DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        Request request = new DownloadManager.Request(Uri.parse(url));
        request.setMimeType(mimeType);

        //Persist download notification in the status bar after the download completes (Android 3.0+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        }

        dm.enqueue(request);
    }

});
person Jose Antonio Escobar Garcia    schedule 02.10.2014