web-dev-qa-db-fra.com

Éviter les problèmes de contenu lors du téléchargement d'un fichier via un navigateur sur Android

Si un fichier est mis à la disposition d'un navigateur par le biais de mon application Web, je règle normalement l'URL à quelque chose comme http://website.com/webapp/download/89347/image.jpg. J'ai ensuite défini les en-têtes HTTP Content-Type: application/octet-stream; filename=image.jpg et Content-Disposition: Attachment.

Cependant, sur Android. Il semble que le seul moyen de télécharger le fichier consiste à définir Content-Type: image/jpg. Sinon, le nom de fichier dit <Unknown> et une erreur survient 

Téléchargement infructueux
Ne peut pas télécharger. Le contenu n'est pas pris en charge sur ce téléphone

Existe-t-il un moyen de télécharger et d’ouvrir le fichier via Android via Android sans conserver la liste des types MIME?

15
George Bailey

Pour que les téléchargements fonctionnent avec toutes les versions d'Android (et en particulier les plus anciennes) comme prévu, vous devez ...

  1. définir le ContentType sur application/octet-stream
  2. mettez la valeur du nom de fichier Content-Disposition entre guillemets
  3. écrire l'extension de nom de fichier Content-Disposition dans UPPERCASE

Lisez mon blog pour plus de détails:
http://digiblog.de/2011/04/19/Android-and-the-download-file-headers/

24
Jpsy

Dmitriy (ou d'autres recherchant une solution possible) si une page html apparaît dans votre fichier téléchargé, je suppose que cela est dû au double problème HttpRequest GET. Un scénario typique est le modèle suivant POST, Redirect, GET:

  • Le navigateur Android envoie un HttpRequest POST au serveur (par exemple, un bouton ou un lien pour demander un fichier de téléchargement, nom_fichier.ext).

  • Le serveur diffuse en octets le nom de fichier demandé.ext demandé, le stocke dans une variable de session, puis émet un Response.Redirect à Download.aspx, par exemple, pour gérer la construction de l'objet de réponse.

  • Le navigateur Android envoie correctement HttpRequest GET au serveur pour Download.aspx

  • Le serveur répond par Content-Disposition typique: pièce jointe; filename = construction de style "filename.ext" avec l'objet de réponse contenant le nom de fichier demandé.ext, qui correspond aux octets de la variable de session.

  • Je crois que le gestionnaire de téléchargement Android envoie ensuite un autre serveur HttpRequest GET au serveur pour Download.aspx. Je soupçonne que le gestionnaire de téléchargement interprète la réponse "pièce jointe" précédente comme un déclencheur pour envoyer ce deuxième GET.

  • Server (Download.aspx) tente à nouveau de construire l'objet de réponse à renvoyer au navigateur.

  • Le gestionnaire de téléchargement Android télécharge filename.ext, en utilisant le contenu de l’objet de réponse du deuxième Download.aspx.

Dans de nombreux scénarios, ce serait bien. Mais si, par exemple, le serveur dans le code Download.aspx effectue certaines tâches de maintenance et supprime la variable de session lors de son premier appel, la prochaine fois, il n’y aura pas de variable de session. Ainsi, en fonction de la manière dont le code est écrit, il est possible que l'objet de réponse ne soit pas explicitement construit et que Response.End ne soit pas appelé, de sorte que seul le code html de Download.aspx soit envoyé.

C’est ce que nous avons découvert avec Wireshark, bien que j’admette que je suppose que c’est le gestionnaire de téléchargement Android qui est à l’origine du double GET.

J'espère que cette explication vous a été utile.

10
StevePayne

Comme je l'ai écrit à télécharger des fichiers depuis Android :

Le navigateur Android ne téléchargera pas le fichier dans le bouton Publier des événements. Dans les événements postérieurs, le fichier sera un fichier .htm garbage. pour venir ce faire comme ci-dessous.

Dans le bouton de téléchargement, cliquez sur

 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.
2
Martin K Abraham

J'ai essayé toutes les recommandations du blog Jspy et rien n'a fonctionné jusqu'à présent. Content-disposition amène le navigateur en mode de téléchargement, mais rien n'est téléchargé sauf le code HTML de la page à partir de laquelle le téléchargement a été lancé. Donc, ma conclusion, c’est un pur bogue de Google et nous ne pouvons que prier pour que Google le répare. Mon travail consistait à définir le type de contenu sur un type provenant du navigateur en-tête Accepter sous forme d'en-tête. Cela fonctionne généralement, vous pouvez même télécharger des fichiers Zip sous forme de texte.

0
Dmitriy R

En théorie, le paramètre filename devrait être défini sur Content-Disposition, pas Content-Type. Pas sûr que cela aidera avec le navigateur Android.

0
Julian Reschke