49 votes

Comment encoder en UTF8 nom de fichier pour les en-têtes HTTP? (Python, Django)

J'ai un problème avec les en-têtes HTTP, ils sont codés en ASCII et je veux avoir une vue de téléchargement de fichiers dont les noms peuvent être non ASCII.

response['Content-Disposition'] = 'attachment; filename="%s"' % (vo.filename.encode("ASCII","replace"), )

Je ne veux pas utiliser les fichiers statiques de servir le même problème avec les fichier ASCII dans les noms, mais dans ce cas il y aurait un problème avec le système de Fichiers et c'est l'encodage du nom de fichier. (Je ne sais pas os cible.)

J'ai déjà essayé urllib.quote(), mais elle pose KeyError exception.

J'ai peut-être fais quelque chose de mal, mais c'est peut-être impossible.

35voto

Julian Reschke Points 12698

C'est une FAQ.

Il n'est pas interopérable façon de le faire. Certains navigateurs extensions propriétaires (IE, Chrome), d'autres de mettre en œuvre la RFC 2231 (Firefox, Opera).

Voir des cas de test à http://greenbytes.de/tech/tc2231/.

Mise à jour: novembre 2012, tous les navigateurs de bureau de support de l'encodage défini dans la RFC 6266 et RFC 5987 (Safari >= 6, IE >= 9, Chrome, Firefox, Opera, Konqueror).

31voto

bobince Points 270740

N'envoyez pas un nom de fichier dans Content-Disposition. Il n'y a aucun moyen de faire de la non-ASCII paramètres d'en-tête de travail de la croix-navigateur(*).

Au lieu de cela, envoyez simplement "Content-Disposition: attachment", et laissez le nom de fichier sous forme d'une URL-encodé en UTF-8 chaîne dans la fuite (PATH_INFO) la partie de votre URL, le navigateur ramasser et utiliser par défaut. UTF-8, les Url sont traitées beaucoup plus fiable par les navigateurs que rien à voir avec le Contenu de la Disposition.

(*: en fait, il n'est même pas un standard actuel qui dit comment il devrait être fait que les relations entre les Rfc 2616, 2231 et 2047 sont assez dysfonctionnel, quelque chose que Julian est d'essayer d'obtenir effacée jusqu'à un niveau spec. Cohérente de la prise en charge du navigateur est dans un futur lointain.)

30voto

Alan H. Points 3580

Note qu'en 2011, RFC 6266 (en particulier l'Annexe D) a pesé sur cette question et a adopté des recommandations spécifiques à suivre.

A savoir, vous pouvez émettre un filename avec uniquement des caractères ASCII, suivie par filename* avec un RFC 5987 format de nom de fichier pour les agents que de le comprendre.

Typiquement, cela va ressembler filename="my-resume.pdf"; filename*=UTF-8''My%20R%C3%A9sum%C3%A9.pdf, d'où le nom de fichier Unicode ("Mon Cv.pdf") est encodé en UTF-8 puis pour cent codé (remarque: ne PAS utiliser + pour les espaces).

S'il vous plaît ne fait lire les RFC 6266 et RFC 5987 (ou utiliser un robuste et éprouvée de la bibliothèque qui fait abstraction de cela pour vous), que mon résumé est ici manque en détail important.

1voto

Jetez un oeil à cette extraits de coder non ascii noms de fichiers http://www.djangosnippets.org/snippets/1710/

-1voto

anon Points 1

Un hack:

if (Request.UserAgent.Contains("IE"))
{
  // IE will accept URL encoding, but spaces don't need to be, and since they're so common..
  filename = filename.Replace("%", "%25").Replace(";", "%3B").Replace("#", "%23").Replace("&", "%26");
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X