Читайте дані файлів, не зберігаючи їх у колбі


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' містила вміст / дані файлу .. будь-які ідеї?

Відповіді:


137

FileStorageмістить streamполе. Цей об'єкт повинен розширювати IO або файл-об'єкт, тому він повинен містити readй інші подібні методи. FileStorageтакож розширити streamатрибути об'єкта поля, тому ви можете просто використовувати file.read()замість цього file.stream.read(). Також ви можете використовувати saveаргумент з dstпараметром як StringIOабо інший IO або об'єкт файлу для копіювання FileStorage.streamв інший IO або файл-об'єкт.

Дивіться документацію: http://flask.pocoo.org/docs/api/#flask.Request.files та http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


1
швидкий приклад:file = request.files.get('file') filetype = magic.from_buffer(file.read(1024))
ендоліт

7
привіт @ user2480542. Я стикаюся з тією ж проблемою. Чи можете ви описати, як ви читали вміст завантаженого клієнтом файлу? Я дзвоню file.read (), але нічого не отримую. Дякую!
tmthyjames

1
@tmthyjames f = request.files['file']ставить завантажений файл (у запиті) у var ("f"). Потім f.read()працює з використанням вищевказаного коду. коли print f.read()я правильно шукаю мотлох в терміналі. Сподіваюся, що це допомагає.
Марк

6
Якщо ви завантажуєте файл і маєте двійковий потік, ви можете легко перетворити його в текстовий потік, загорнувши його в TextIOWrapper: mystring = TextIOWrapper(binary_stream)
Dutch Masters

6
f.read()теж нічого не дало для мене. Подзвонивши першим, f.seek(0)зробив для мене трюк.
w177us

11

Якщо ви хочете використовувати стандартний матеріал на колбі - немає жодного способу уникнути збереження тимчасового файлу, якщо розмір завантаженого файлу> 500 кб. Якщо він менше 500 кбіт - він буде використовувати "BytesIO", який зберігає вміст файлу в пам'яті, а якщо він перевищує 500 кбіт - він зберігає вміст у TemporaryFile () (як зазначено в документації werkzeug ). В обох випадках ваш сценарій буде заблокований, поки не буде отримано весь завантажений файл.

Найпростіший спосіб обійти це, що я знайшов:

1) Створіть власний клас схожих на файли вводу-виводу, де ви виконуєте всю обробку вхідних даних

2) У вашому сценарії замініть Запит класу на свій власний:

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

3) Замініть запитний_клас Flask власним:

app.request_class = MyRequest

4) Піди попити пива :)


0

Я намагався зробити саме те саме, відкрити текстовий файл (фактично CSV для Pandas). Не хочете робити його копію, просто потрібно відкрити її. Форма-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) 

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


-1

У випадку, якщо ми хочемо скинути файл пам'яті на диск. Цей код можна використовувати

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()

-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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.