БетаЛаборатория - внеочередной IT-блог

Записки обычного программиста

 

Записи с тэгом SHA1Storage

Хэширование имен загружаемых файлов в Django, часть вторая

В прошлой реализации хранилища файлов с хэшированием имен файлы были доступны клиентам сайта по хэшированному имени, что не всегда удобно — файлы, передаваемые клиентам сайта, не имели осмысленных имён. Решая эту проблему, все хранилище было переработано и теперь представляет собой приложение. Кроме того, требуется дополнительно настроить frontend-сервер. Для начала несколько слов о самом принципе работы системы:
 Схема работы Django SHA1Storage:
  • 1. Клиент запрашивает файл у веб-сервера (frontend, в нашем случае это nginx).
  • 2. nginx перенаправляет запрос к Django (backend), согласно параметрам локации (location), которой соответствует URI запрошенного файла.
  • 3. Django принимает запрос, обрабатывает URL и возвращает nginx'у ответ с кодом 200, содержащий реальный путь до файла (в заранее заданной локации) в заголовке X-Accel-Redirect, а также тип содержимого файла в заголовке Content-type, основанный на расширении изначального имени файла.
  • 4, 5, 6. nginx обрабатывает путь в X-Accel-Redirect и в ответ на исходный запрос (пункт 1) клиента передаёт ему файл из директории, соответствующей локации, если файл найден. Заголовок Content-type, полученный от Django, при этом сохраняется.
Теперь обо всем по порядку. В первую очередь настроим frontend:
    server {
    listen mysite.ru:80;
    server_name mysite.ru www.mysite.ru;

# Нам совершенно не обязательно проксировать все запросы.
# Поэтому ограничиваемся проверкой запросов вида
# http://mysite.ru/media/upload/some_file.ext

# Передаём изменённый GET-запрос Django. В ответ мы должны получить ответ с
# заголовком X-Accel-Redirect.
    location /media/upload {
        rewrite ^/media/upload/(.*) /nginx/?filename=upload/$1 break;

        fastcgi_pass unix:/path/to/django's/fcgi.sock;
        include /etc/nginx/fastcgi_params;
    }
 

# Эта локация отражает реальный путь до директории хранилища наших файлов.
# Именно сюда Django будет ссылаться в X-Accel-Redirect.
# Прямой доступ к файлам клиентам сайта запрещён (для этого нужна директива internal).
    location /sha1storage {
        internal;
        alias /path/to/project/media/sha1storage;
    }

# Запрещаем  клиентам сайта прямые запросы к Django в локацию /nginx
    location /nginx {
        internal;
    }
 

# Запрещаем клиентам сайта прямой доступ к файлам хранилища в обход Django
    location /media/sha1storage {
        internal;
    }

# Локация с файлами, доступными для загрузки клиентам сайта не из sha1storage.
# Сюда Django перенаправит запрос посредством X-Accel-Redirect, если не
# найдёт файл в sha1storage.
    location /upload {
       internal;
       alias /home/www/www51/betalabs.ru/media/upload;
    }
}
Как это все в итоге работает: nginx получает запрос от клиента. Если путь запрашиваемого файла начинается с /media/upload/, то делается запрос к Django по адресу вида '/nginx/?filename=upload/filename.ext', с передачей в GET-переменной filename пути до файла, с указанием изначального имени. Обратите внимание, что в запросе к Django обрезается /media/, поскольку Django всегда работает с файлами внутри директории, указанной в MEDIA_ROOT.
 
Для настройки django нам понадобиться приложение SHA1Storage.
 
ВНИМАНИЕ. На данный момент приложение находится в стадии beta-тестирования и имеет некоторые ограничения в настройке, которые, я надеюсь, в ближайшее время будут ликвидированы. Если вы найдете какие-то баги, буду очень благодарен за багрепорт.
 
Для установки добавляем его в INSTALLED_APPS:
 
INSTALLED_APPS = (
    'sha1storage',
)

# Если хотите использовать это хранилище как основное, можно указать параметр DEFAULT_FILE_STORAGE.
DEFAULT_FILE_STORAGE = 'sha1storage.storage.SHA1FilenameFileSystemStorage'
 
Если вы хотите использовать хранилище только для отдельных файлов, то к полю файла в модели необходимо добавить свойство storage.
 
В urls.py необходимо добавить обработку URL обработчика sha1storage:
urlpatterns = patterns('',
 (r'nginx/', 'sha1storage.views.get_real_filename'),
);
В принципе это все. Теперь при загрузке файла его имя будет хэшироваться, и он будет сохраняться в папку /path/to/project/media/sha1storage/upload_to_mode_field_path/. При этом модели будет передаваться не хэш от имени файла, а само имя. Из дополнительных особенностей: все файлы, кроме стандартной графики, sha1storage возвращает с заголовком Content-Disposition: attachment, в качестве полумеры для закрытия XSS-уязвимостей, пока не реализованы более строгие алгоритмы защиты.

Авторизация

Логин:

Пароль:


Регистрация | Забыли пароль?


Последние записи


Promo

Follow pyhoster on Twitter Subscribe

Реклама

A Django project.