Как получить данные в виде объекта File на flask веб-сервере? - PullRequest
0 голосов
/ 14 февраля 2020

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

HTML Код:

<canvas id="myCanvas">
        Sorry, your browser does not support HTML5 canvas technology.
</canvas>
<button onclick="clickonbutton()">Upload</button>

Canvas используется для рисования ди git и кнопки для отправки ее на веб-сервер flask.

Javascript Код:

<script type="text/javascript">
function clickonbutton() {
        var canvas = document.getElementById('myCanvas');

        //Convert HTML5 Canvas to bytes-like object then File object
        canvas.toBlob(function(blob) {
                var file = new File([blob], "image.png", { type: "image/png", lastModified : new Date()});

                //Prepare a XMLHttpRequest to send the data with POST method to the server
                var request = new XMLHttpRequest();
                request.open("POST", "/");
                request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                //Sending file...
                request.send(file);
         });
}               
</script>

Когда пользователь нажимает кнопку «Загрузить» "после редактирования холста HTML5 он запускает эту функцию, которая отправляет файл на сервер.

Python скрипт (на стороне сервера):

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        #Convert MultiDict to Dict object then string
        data = str(request.form.to_dict())

        #Format string to remove Dict elements
        data = data.replace("{","")
        data = data.replace("}","")
        data = data.replace("'","")
        data = data.replace(": ","")

        #Convert string to bytes-like object
        img_bytes = data.encode()

        #Predict the digit of the user
        _, predicted_class, probabilities = get_prediction(image_bytes=img_bytes)
        predicted_class = int(predicted_class)
        classify(img=_, ps=probabilities)

        #Return the result of the digit prediction
        return render_template('result.html',class_name=predicted_class)
    return render_template('index.html')

на стороне сервера я получаю данные из request.form, но они находятся в объекте ImmutableMultiDict, поэтому я преобразовал данные в строку, а затем в байтовый объект. К сожалению, преобразование с использованием метода .replace () повреждает файл PNG, и нет средства для правильного выполнения этого преобразования ...

Существует ли решение для получения данных непосредственно в объекте File без использования объекта ImmutableMultiDict

1 Ответ

0 голосов
/ 14 февраля 2020

Итак, с помощью этой темы об использовании Fetch API и этого ответа на HTML5 холст для рисования Я подумал, что это можно сделать с помощью чего-то вроде:

<div id='sketch'>
  <canvas id="myCanvas">
  </canvas>
</div>

<button id='btn'>Upload</button>

<div id='result' style='font-size:2em;'></div>

Обратите внимание, что я добавил div для вывода результатов (имя класса) на той же странице.

Затем в Javascript используйте объект FormData: (Я пропустил функция рисования для ясности):


// Define the dom elements
const canvas = document.getElementById('myCanvas');
const btn = document.getElementById('btn');
const result = document.getElementById('result');

// This will handle the upload
const upload = (file) => {
  fetch('/', { // Your POST endpoint
    method: 'POST',
    body: file // This is your file object
  }).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => { result.innerText = success['class_name']; } // Write class_name into results div.
  ).catch(
    error => console.log(error) // Handle the error response object
  );
};

// Listener which handles the button click:
btn.addEventListener('click', function() {

  canvas.toBlob(function(blob) {
    var data = new FormData();
    data.append('file', blob);
    upload(data);
  });

}, false);

Теперь на стороне сервера это может быть обработано как обычная Flask загрузка файла :

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['file']

        #Convert string to bytes-like object
        img_bytes = file.read()

        #Predict the digit of the user
        _, predicted_class, probabilities = get_prediction(image_bytes=img_bytes)
        predicted_class = int(predicted_class)
        classify(img=_, ps=probabilities)

        #Return the result of the digit prediction
        return {'class_name': predicted_class}
    return render_template('index.html')

Любой почтовый запрос теперь возвращает jsonified словарь, который, в свою очередь, записывается в результаты div на странице.

Возможно, здесь есть место для улучшения, например, некоторая проверка на стороне сервера, а также ограничение скорости и обработка ошибок, но концепция basi c работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...