Flask request.files возвращает ImmutableMultiDict ([]) - PullRequest
0 голосов
/ 18 октября 2018

Я миллион раз пытался заставить это работать.Я делаю веб-приложение, и у меня есть кнопка (модальная), которая появляется, когда пользователь вводит имя и загружает файл.Когда пользователь нажимает на Save Well.Request.files возвращает ImmutableMultiDict ([])

Это кнопка:

Кнопка добавления нового лунки

Код для модального в Интернетестраница:

  $(document).ready(function(){
	$('#SaveNewWellButton').on('click', function(e){
		
    e.preventDefault()
    $.ajax({
		url:'./createNewWellfolder',
        type:'post',
        data:{'newWellNameImported':$("#newWellNameImported").val(), 
		      'WTTcsvfile':$("#WTTcsvfile").val()
		},
		success: function(data){
				//$("#result").text(data.result)
				$('#selectWell').html(data)
				alert( "New well created" );
			},
			error: function(error){
				console.log(error);
			}
        });
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<span class="table-add float-right mb-3 mr-2" data-toggle="modal" data-target="#myModal"> 
  <button type="submit" class="btn btn-success">Add New Well</button></span>
  <!-- The Modal -->
  <div class="modal fade" id="myModal">
    <div class="modal-dialog modal-dialog-centered">
      <div class="modal-content">
      
        <!-- Modal Header -->
        <div class="modal-header">
          <h4 class="modal-title">Import CSV file:</h4>
          <button type="button" class="close" data-dismiss="modal">&times;</button>
        </div>
        
        <!-- Modal body -->
		<form action="/createNewWellfolder" method="post" enctype="multipart/form-data">
        <div class="modal-body">
          Name of well:<input type="text" id="newWellNameImported" class="form-control"></input>
        </div>
        
        <!-- Modal footer -->
        <div class="modal-footer">
		<input type="file" name="csvfile" value ="csvfile" id="csvfile">
		</br>
		  <button type="submit" class="btn btn-primary" id="SaveNewWellButton">Save Well</button>
          <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
        </div>
		 </form>
        
      </div>
    </div>
  </div>

Код Python выглядит следующим образом:

@app.route('/createNewWellfolder', methods=['GET', 'POST'])
def createNewWellfolder():
    print('request.method : %s',  request.method)
    print('request.files : %s', request.files)
    print('request.args : %s', request.args)
    print('request.form : %s', request.form)
    print('request.values : %s', request.values)

Вывод с терминала:

    request.method : %s POST
    request.files : %s ImmutableMultiDict([])
    request.args : %s ImmutableMultiDict([])
    request.form : %s ImmutableMultiDict([('newWellNameImported', 'Sample Well 14')])
    request.values : %s CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([('newWellNameImported', 'Sample Well 14')])])

Просто хотитедобавьте, что приведенный ниже код работает.Но как мне заставить его работать в моем крупном веб-приложении?Я думаю, это как-то связано с app.route.Но я пробовал так много вещей, как добавление его в форму действия с помощью url_for и т. Д. Кажется, ничего не работает.

import os
from flask import Flask, flash, send_from_directory, request, redirect, url_for
from werkzeug.utils import secure_filename
from os.path import dirname, join

DATA_DIR = join(dirname(__file__), 'data/')
wellNames = next(os.walk('data'))[1]

print(DATA_DIR, wellNames[0])

UPLOAD_FOLDER = DATA_DIR + wellNames[0] + '/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'csv', 'docx'])

app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def createNewWellfolder():

    if request.method == 'POST':
        print('------------->', request.files)
    # check if the post request has the file part
        if 'csvfile' not in request.files:
            flash('No file part')
        file = request.files['csvfile']
        print('------------->', file)

        if file.filename == '':
            flash('No selected file')
        if file and allowed_file(file.filename):
            print('hello im here------------->', file)
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

    return '''
    <!-- Modal body -->
    <form method=post enctype=multipart/form-data>
    <div class="modal-body">
      Name of well:<input type="text" id="newWellNameImported" class="form-control"></input>
    </div>

    <!-- Modal footer -->
    <div class="modal-footer">
    <input type=file name="csvfile" id="csvfile" >
    </br>
      <button type="submit" class="btn btn-primary" id="SaveNewWellButton" >Save Well</button>
      <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
    </div>
     </form>
     '''    
   if __name__ == '__main__':
        print('Opening single process Flask app with embedded Bokeh application on http://localhost:8000/')
        app.secret_key = 'secret key'
        app.debug = True
        app.run(port = 8000)

Выход с клеммы:

-------------> ImmutableMultiDict([('csvfile', <FileStorage: 'testcsv.csv' ('application/vnd.ms-excel')>)])
-------------> <FileStorage: 'testcsv.csv' ('application/vnd.ms-excel')>
hello im here-------------> <FileStorage: 'testcsv.csv' ('application/vnd.ms-excel')>

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Не могли бы вы подробнее остановиться на этом вопросе?Ожидается, что Flask Request вернет объект ImmutableMultiDict:

MultiDict, содержащий все загруженные файлы.Каждый ключ в файлах - это имя из <input type="file" name="">.Каждое значение в файлах - это объект Werkzeug FileStorage.

Он в основном ведет себя как стандартный файловый объект, известный вам из Python, с той лишь разницей, что он также имеет функцию save(), которая может хранить файл в файловой системе.

Обратите внимание, что файлы будут содержать данные только в том случае, если метод запроса был POST, PUT или PATCH и <form>, отправленный на запрос, имел enctype="multipart/form-data".В противном случае он будет пустым.

Дополнительные сведения об используемой структуре данных см. В документации MultiDict / FileStorage.

http://flask.pocoo.org/docs/1.0/api/#flask.Request.files

0 голосов
/ 18 октября 2018

Я полагаю, что проблема в вашей сериализации формы.- Попробуйте прочитать this .

Вы также можете использовать что-то похожее на следующее:

(function($) {
  $.fn.serializeFiles = function() {
    var form = $(this),
        formData = new FormData(),
        formParams = form.serializeArray();

    $.each(form.find('input[type="file"]'), function(i, tag) {
      $.each($(tag)[0].files, function(i, file) {
        formData.append(tag.name, file);
      });
    });

    $.each(formParams, function(i, val) {
      formData.append(val.name, val.value);
    });

    return formData;
  };
})(jQuery);

Вы можете устранить, какая часть не работает, не предотвращаяФорма для отправки и посмотреть, если по умолчанию;Форма отправляет файлы на сервер.- Маловероятно, что вы передаете правильные данные в результате сериализации формы.

...