Избегайте проблем с типом контента при загрузке файла через браузер на Android

Если у меня есть файл, доступный браузеру через мой webapp, я обычно устанавливаю URL-адрес примерно как http://website.com/webapp/download/89347/image.jpg. Затем я устанавливаю заголовки HTTP Content-Type: application/octet-stream; filename=image.jpg и Content-Disposition: Attachment.

Однако на Android. Кажется, единственный способ получить файл для загрузки - установить Content-Type: image/jpg. В противном случае имя файла говорит <Unknown> и появляется ошибка

Загрузить неудачный
Не удается загрузить. Содержимое не поддерживается на этом телефоне.

Есть ли способ заставить Android загружать и открывать файл через браузер, не сохраняя список типов mime?

Ответы

Ответ 1

Чтобы сделать загрузку работы на всех (и особенно старых) версиях Android, как и ожидалось, вам нужно...

  • установите ContentType в application/octet-stream
  • введите значение имени файла Content-Disposition в двойные кавычки
  • напишите расширение файла содержимого-Disposition в UPPERCASE

Читайте мой блог для более подробной информации:
http://digiblog.de/2011/04/19/android-and-the-download-file-headers/

Ответ 2

Dmitriy (или другие, которые ищут возможное решение), если в загруженном файле появляется html-страница, я подозреваю, что это связано с двойной проблемой HttpRequest GET. Типичным сценарием является следующая модель POST, Redirect, GET:

  • Android-браузер выдает сообщение об ошибке HttpRequest POST на сервер (например, кнопку отправки или ссылку для запроса файла загрузки, filename.ext say)

  • Сервер передает запрашиваемое имя файла .ext в байты, сохраняет в переменной сеанса, а затем выдает Response.Redirect для Download.aspx, например, для обработки конструкции объекта ответа

  • Android-браузер правильно отправляет HttpRequest GET на сервер для Download.aspx

  • Сервер отвечает типичным Content-Disposition: attachment; filename = "filename.ext" с объектом ответа, содержащим запрошенный filename.ext, являющийся байтами в переменной сеанса.

  • Менеджер загрузки Android, я полагаю, затем отправляет еще один HttpRequest GET на сервер для Download.aspx. Я подозреваю, что менеджер загрузок интерпретирует предыдущий ответ "вложения" как триггер для отправки второго GET.

  • Сервер (Download.aspx) снова пытается создать объект ответа для отправки обратно в браузер.

  • Менеджер загрузки Android загружает файл filename.ext, используя содержимое объекта ответа из второго Download.aspx.

Во многих сценариях это будет хорошо. Но если, например, сервер в коде Download.aspx выполняет некоторую утилизацию и удаляет переменную сеанса при первом вызове, тогда в следующий раз нет никакой переменной сеанса. Таким образом, в зависимости от того, как написан код, возможно, что объект ответа не получает конструкцию объяснений, и, возможно, Response.End не вызывается, и поэтому отправляется только Download.aspx html.

Это то, что мы обнаружили с помощью Wireshark, хотя я признаю, что я предполагаю, что это менеджер загрузки Android, который является причиной двойного GET.

Надеюсь, что это объяснение было полезным.

Ответ 3

Как я писал в загрузке файлов с android:

Android-браузер не будет загружать файл в кнопку "Опубликовать события". В сообщениях событий файл будет представлять собой файл .htm для мусора. чтобы сделать это, как показано ниже.

В режиме загрузки нажмите кнопку

 protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
    {
        Response.Redirect("download-file.aspx");
    }

and on  download-file.aspx file do as below

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class mobile_download_file : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string filename = "usermanual.pdf";
        Response.ContentType = "application/octet-stream";
        Response.AppendHeader("Content-Disposition", "attachment; filename=" + "" + filename + "");
        Response.Write(Server.MapPath(Request.ApplicationPath) + "\\" + filename);
        Response.TransmitFile(Server.MapPath(Request.ApplicationPath) + "\\" + filename);
        Response.End();
    }
}

the same can be implemented in php also.

Ответ 4

Я пробовал все рекомендации из блога Jspy, и пока ничего не работало. Контент-расположение приводит браузер в режим загрузки, однако ничто не загружается, кроме HTML-страницы, с которой начата загрузка. Итак, мой вывод, это чистая ошибка от Google, и мы можем молиться только за то, что Google исправил ее. Моя работа заключалась в том, чтобы задать тип содержимого для какого-либо типа, исходящего из мобильного браузера Accept header form. Он вообще работает, вы даже можете загружать zip файлы в виде текста.

Ответ 5

В теории параметр filename должен быть установлен в Content-Disposition, а не Content-Type. Не уверен, поможет ли это в браузере Android.