Чтение данных файла без сохранения во Flask

112

Я пишу свое первое приложение для фляги. Я имею дело с загрузкой файлов, и в основном я хочу прочитать данные / содержимое загруженного файла, не сохраняя его, а затем распечатать его на полученной странице. Да, я предполагаю, что пользователь всегда загружает текстовый файл.

Вот простая функция загрузки, которую я использую:

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        if file:
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            a = 'file uploaded'

    return render_template('upload.html', data = a)

Прямо сейчас я сохраняю файл, но мне нужна переменная 'a', которая будет содержать содержимое / данные файла ... какие-нибудь идеи?

user2480542
источник

Ответы:

137

FileStorageсодержит streamполе. Этот объект должен расширять ввод-вывод или объект файла, поэтому он должен содержать readи другие подобные методы. FileStorageтакже расширяют streamатрибуты объекта поля, поэтому вы можете просто использовать file.read()вместо них file.stream.read(). Также вы можете использовать saveаргумент с dstпараметром as StringIOили другой объект ввода-вывода или файл для копирования FileStorage.streamв другой объект ввода-вывода или файл.

См. Документацию: http://flask.pocoo.org/docs/api/#flask.Request.files и http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .

tbicr
источник
1
быстрый пример:file = request.files.get('file') filetype = magic.from_buffer(file.read(1024))
endolith
7
привет @ user2480542. У меня та же проблема. Можете ли вы описать, как вы читали содержимое загруженного клиентом файла? Я вызываю file.read (), но ничего не получаю. Спасибо!
tmthyjames
1
@tmthyjames f = request.files['file']помещает загруженный файл (в запросе) в переменную ("f"). Затем f.read()работает с использованием приведенного выше кода. когда print f.read()я получаю правильно выглядящий хлам в терминале. Надеюсь, это поможет.
Marc
6
Если вы загружаете файл и у вас есть двоичный поток, вы можете легко преобразовать его в текстовый поток, обернув его в TextIOWrapper: mystring = TextIOWrapper(binary_stream)
Dutch Masters
7
f.read()мне тоже ничего не дало. Звонок первым f.seek(0)помог мне.
w177us
12

Если вы хотите использовать стандартные вещи Flask - нет никакого способа избежать сохранения временного файла, если размер загруженного файла> 500 КБ. Если он меньше 500 КБ - он будет использовать «BytesIO», который хранит содержимое файла в памяти, а если больше 500 КБ - он сохраняет содержимое в TemporaryFile () (как указано в документации werkzeug ). В обоих случаях ваш скрипт будет заблокирован до тех пор, пока не будет получен весь загруженный файл.

Самый простой способ обойти это, что я нашел:

1) Создайте свой собственный файловый класс ввода-вывода, в котором вы выполняете всю обработку входящих данных

2) В вашем скрипте переопределите класс Request своим собственным:

class MyRequest( Request ):
  def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ):
    return MyAwesomeIO( filename, 'w' )

3) Замените request_class Flask своим:

app.request_class = MyRequest

4) Иди, выпей пива :)

Димитри Майлз
источник
0

Я пытался сделать то же самое, открыть текстовый файл (на самом деле CSV для Pandas). Не хочу копировать, просто хочу открыть. У form-WTF есть хороший файловый браузер, но затем он открывает файл и создает временный файл, который представляет как поток памяти. Немного поработав под капотом,

form = UploadForm() 
 if form.validate_on_submit(): 
      filename = secure_filename(form.fileContents.data.filename)  
      filestream =  form.fileContents.data 
      filestream.seek(0)
      ef = pd.read_csv( filestream  )
      sr = pd.DataFrame(ef)  
      return render_template('dataframe.html',tables=[sr.to_html(justify='center, classes='table table-bordered table-hover')],titles = [filename], form=form) 
TGanoe
источник
0

Я делюсь своим решением (при условии, что все уже настроено для подключения к ведру Google в колбе)

from google.cloud import storage

@app.route('/upload/', methods=['POST'])
def upload():
    if request.method == 'POST':
        # FileStorage object wrapper
        file = request.files["file"]                    
        if file:
            os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = app.config['GOOGLE_APPLICATION_CREDENTIALS']
            bucket_name = "bucket_name" 
            storage_client = storage.Client()
            bucket = storage_client.bucket(bucket_name)
            # Upload file to Google Bucket
            blob = bucket.blob(file.filename) 
            blob.upload_from_string(file.read())

Мой пост

Прямо в Google Bucket во флаконе

Jamartincelis
источник
-1

Мы просто сделали:

import io
from pathlib import Path

    def test_my_upload(self, accept_json):
        """Test my uploads endpoint for POST."""
        data = {
            "filePath[]": "/tmp/bin",
            "manifest[]": (io.StringIO(str(Path(__file__).parent /
                                           "path_to_file/npmlist.json")).read(),
                           'npmlist.json'),
        }
        headers = {
            'a': 'A',
            'b': 'B'
        }
        res = self.client.post(api_route_for('/test'),
                               data=data,
                               content_type='multipart/form-data',
                               headers=headers,
                               )
        assert res.status_code == 200
Дипак Шарма
источник
-1

в функции

def handleUpload():
    if 'photo' in request.files:
        photo = request.files['photo']
        if photo.filename != '':      
            image = request.files['photo']  
            image_string = base64.b64encode(image.read())
            image_string = image_string.decode('utf-8')
            #use this to remove b'...' to get raw string
            return render_template('handleUpload.html',filestring = image_string)
    return render_template('upload.html')

в html файле

<html>
<head>
    <title>Simple file upload using Python Flask</title>
</head>
<body>
    {% if filestring %}
      <h1>Raw image:</h1>
      <h1>{{filestring}}</h1>
      <img src="data:image/png;base64, {{filestring}}" alt="alternate" />.
    {% else %}
      <h1></h1>
    {% endif %}
</body>

Triết Nguyễn Vnh
источник
-2

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

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()
лалит
источник