2016-02-29 1 views
1

Я использую приложение Flask для получения запроса mutipart/form-data с загруженным файлом (видео в этом примере).Флажок - Обращение с файлом формы и загрузка в AWS S3 без сохранения в файл

Я не хочу сохранять файл в локальном каталоге, потому что это приложение будет работать на сервере, и его сохранение замедлит работу.

Я пытаюсь использовать файл-объект, созданный методом Flask request.files [''], но он, похоже, не работает.

Вот та часть кода:

@bp.route('/video_upload', methods=['POST']) 
def VideoUploadHandler(): 
    form = request.form 
    video_file = request.files['video_data'] 
    if video_file: 
     s3 = boto3.client('s3') 
     s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4') 
     return json.dumps('DynamoDB failure') 

Это возвращает ошибку:

TypeError: must be encoded string without NULL bytes, not str 

на линии:

s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4') 

я получить эту работу по первому сохраняя файл и затем получая доступ к этому сохраненному файлу, поэтому это не проблема с поиском файла запроса. Это работает:

video_file.save(form['video_id']+".mp4") 
s3.upload_file(form['video_id']+".mp4", S3_BUCKET, form['video_id']+".mp4") 

Что бы быть лучшим методом для обработки Этот файл данных в памяти и передать его методу s3.upload_file()? Я использую методы boto3 here, и я только нахожу примеры с именем файла, используемым в первом параметре, поэтому я не уверен, как правильно обрабатывать этот файл в памяти. Благодаря!

+0

вам удалось этот вопрос? – cuongnv23

ответ

1

Сначала вам нужно иметь доступ к необработанным данным, отправленным в Flask. Это не так просто, как кажется, поскольку вы читаете форму. Чтобы читать исходный поток, вы можете использовать flask.request.stream, который ведет себя аналогично StringIO. Фокус здесь, вы не может позвонить request.form или request.file, потому что доступ к этим атрибутам будет загружать весь поток в память или в файл.

Вам понадобится дополнительная работа по извлечению правой части потока (к сожалению, я не могу вам помочь, потому что это зависит от того, как ваша форма создана, но я позволю вам поэкспериментировать с этим).

Наконец, вы можете использовать функцию set_contents_from_file от boto, так как upload_file, похоже, не имеет дело с файлоподобными объектами (StringIO и т. Д.).

Пример кода:

from boto.s3.key import Key 

@bp.route('/video_upload', methods=['POST']) 
def VideoUploadHandler(): 
    # form = request.form <- Don't do that 
    # video_file = request.files['video_data'] <- Don't do that either 
    video_file_and_metadata = request.stream # This is a file-like object which does not only contain your video file 
    # This is what you need to implement 
    video_title, video_stream = extract_title_stream(video_file_and_metadata) 
    # Then, upload to the bucket 
    s3 = boto3.client('s3') 
    bucket = s3.create_bucket(bucket_name, location=boto.s3.connection.Location.DEFAULT) 
    k = Key(bucket) 
    k.key = video_title 
    k.set_contents_from_filename(video_stream) 
+0

Спасибо за помощь! Можете ли вы подробнее описать 'extract_title_stream (video_file_and_metadata)'? Я новичок в этом, поэтому я не уверен, с чего начать извлечение этого потока, который отличается от того, что я уже делал. – Feedslant

+0

Ну, как я уже сказал, это характерно для ваших форм, поэтому вы должны взглянуть на него сами ... Посмотрите на https://docs.python.org/2/library/stringio.html. Может быть метод 'get_value' для' request.stream', но я не уверен. ИМО лучше всего обрабатывать ваши файлы так, как вы их использовали: это безопаснее, и я не уверен, что вам нужна дополнительная производительность. –

+0

Возможно, это связано с тем, что я новичок в библиотеке stringIO и потоковой передаче, но я не уверен, как преобразовать лимитированный поток ('request.stream') в stringIO. Я не нахожу много информации об этом онлайн. – Feedslant