Znaki diakrytyczne w plikach uploadowanych przez Django i Apache’a
Django na ogół znakomicie radzi sobie z obsługą znaków diakrytycznych i możemy śmiało używać ogonków w aplikacjach pisanych za pomocą tego frameworka. Możemy jednak natknąć się na problem, jeżeli spróbujemy za pomocą formularza wysłać na serwer plik z nazwą zawierającą nasze ogonki:
Exception Type: UnicodeEncodeError Exception Value: 'ascii' codec can't encode characters in position 46-49: ordinal not in range(128)
Błąd leży tu jednak nie po stronie Django, a Apache’a, o czym piszą twórcy frameworka:
If you get a UnicodeEncodeError =============================== If you're taking advantage of the internationalization features of Django (see :ref:`topics-i18n`) and you intend to allow users to upload files, you must ensure that the environment used to start Apache is configured to accept non-ASCII file names. If your environment is not correctly configured, you will trigger ``UnicodeEncodeError`` exceptions when calling functions like ``os.path()`` on filenames that contain non-ASCII characters. To avoid these problems, the environment used to start Apache should contain settings analogous to the following:: export LANG='en_US.UTF-8' export LC_ALL='en_US.UTF-8' Consult the documentation for your operating system for the appropriate syntax and location to put these configuration items; ``/etc/apache2/envvars`` is a common location on Unix platforms. Once you have added these statements to your environment, restart Apache.
Dopisujem zatem do /etc/apache2/envvars:
export LANG='en_US.UTF-8' export LC_ALL='en_US.UTF-8'
Ewentualnie możemy wyedytować zmienną ENV w pliku /etc/init.d/apache2 (oczywiście, jest to mniej eleganckie rozwiązanie), np.:
ENV="env -i LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 PATH=/usr/local/bin:/usr/bin:/bin"
Teraz Apache powinien uruchamiać się ze zmiennymi środowiskowymi, które nakażą mu korzystanie z Unicodu. Okazuje się jednak, że to nie koniec przygód, bo, zwracając plik użytkownikowi, otrzymamy:
Exception Type: UnicodeEncodeError Exception Value: 'ascii' codec can't encode characters in position 23-26: ordinal not in range(128), HTTP response headers must be in US-ASCII format
Okazuje się, że nagłówek HTTP nie może zostać prawidłowo zakodowany. Musimy więc pomóc Django, jawnie kodując nazwę pliku w obiekcie HttpResponse za pomocą metody encode(). Tym samym zamiast:
response = HttpResponse(open(path), mimetype='%s' % (mimetypes.guess_type(path)[0])) response['Content-Disposition'] = 'attachment; filename=%s' % (myfile.filename())
powinniśmy użyć:
response = HttpResponse(open(path), mimetype='%s' % (mimetypes.guess_type(path)[0]))
response['Content-Disposition'] = 'attachment; filename="%s"' % (myfile.filename().encode('utf-8'))
