zlukfo@gmail.com
  • Публикации
  • Темы
  • Ключевые слова
  • Архив

Apache: управление загрузкой файлов с помощью wsgi

Загрузка файлов на http сервер выполняется методом POST. Большие файлы передаваются несколькими запросами.

В качестве url POST-запроса указывается скрипт-обработчик, в нашем случае скрипт wsgi. Обработчик должен брать на себя полностью управление загрузкой - контроль типа файла, размера, количества загружаемых файлов.

В принципе, управление загрузкой файлов на сервер можно управлять без подключения дополнительных модулей, напрямую обращаясь к переменной окружения environ['wsgi.input']. Но удобнее воспользоваться модулем cgi. Ниже приведен пример функции, которая анализирует запрос с переданными для загрузки файлами и возвращает информацию об этих файлах. При этом загружать сами файлы пока не будем

import cgi
def application(environ, start_response):

        formdata = cgi.FieldStorage(environ=environ, fp=environ['wsgi.input'])

        l=formdata.list
        output= 'Files count: %d. Size all files: %d\r\n' % (len(l), formdata.length)
        # отображаемый размер будет на пару сотен байт больше суммарного размера файлов (это заголовки)

        for i in xrange(len(l)):
                output+='Filename: %s, type: %s\r\n' % (l[i].filename, l[i].type)

        status = '200 OK'
        response_headers = [
                ('Content-Type', 'text/plain'),
                ('Content-Length', str(len(output)))
        ]

        start_response(status, response_headers)
        return [output]

Проследить как работает скрипт можно, например, воспользовавшись утилитой curl

curl  -F name1=@test1.txt -F name2=@test2.txt http://tests/ul

Для сохранения переданных файлов можно применить функцию приведенную ниже. В функцию добавлены следующие типы проверок: * по количеству загружаемых файлов * по размеру каждого загружаемого файла * по типу файла (по его расширению)

from tempfile import TemporaryFile
import cgi

def application(environ, start_response):
        output=upload(environ)

        status = '200 Ok'
        response_headers = [
                        ('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(output)))
        ]
        start_response(status, response_headers)
        return [output]

def upload(environ):
        MAX_COUNT_FILES=2
        MAX_FILE_SIZE=2024*2
        EXTENSION=['txt','json', 'csv']

        formdata = cgi.FieldStorage(environ=environ, fp=environ['wsgi.input'])
        output=''

        files_list=formdata.list
        count=len(files_list)

        # проверка по количеству
        if count>MAX_COUNT_FILES:
                output='\nAttempt upload %d files. Max count - %d. Files not uploaded\n' % (count, MAX_COUNT_FILES)
                return output

        for i in xrange(count):
                # проверка по расширению
                ext=files_list[i].filename.split('.')[-1]
                if ext not in EXTENSION:
                        output+='File %s has invalid type. Must be %s\n' % (files_list[i].filename, str(EXTENSION))
                        continue
                # проверка по размеру
                body=files_list[i].file
                body.seek(0, 2)
                if body.tell()>MAX_FILE_SIZE:
                        output+='File %s has large size. Max file size - %d\n' % (files_list[i].filename, MAX_FILE_SIZE)
                        continue
                body.seek(0)

                # сохранение во временный файл с дополнительным контролем размера
                temp_f = TemporaryFile()
                m=MAX_FILE_SIZE
                while m > 0:
                        part = body.read(min(m, 1024*200))
                        if not part: break
                        temp_f.write(part)
                        m -= len(part)
                if part:
                        continue

                f=open('/var/www/tests/upload/'+files_list[i].filename,'wb')
                temp_f.seek(0)
                f.write(temp_f.read())
                f.close()
                temp_f.close()
                output+= 'File %s uploaded\n' % files_list[i].filename

        return output

Опубликовано

авг. 7, 2016

Тема

Инструменты разработки

Ключевые слова

  • apache 2
  • wsgi 2
  • zlukfo@gmail.com - Публикации на тему разработки web-приложений
  • Все авторские права защищены
  • Автор и разработчик блога zlukfo. Theme: Elegant by Talha Mansoor