簡體   English   中英

Flask 正在接收 GET 請求而不是 POST

[英]Flask is receiving a GET request instead of POST

我正在創建一個 web 應用程序,它在瀏覽器中記錄音頻並將其發送到 flask 后端,用於語音到文本的轉錄和意圖分類。 當我在不檢查方法的情況下運行代碼時(代碼被注釋掉),這就是命令行顯示的內容。

127.0.0.1 - - [11/Jan/2021 06:50:00] "GET /result HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\Admin\Desktop\Voice Assistant web\voice_assistant.py", line 22, in result
    file = request.files['audio_data']
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\debughelpers.py", line 96, in __getitem__
    return oldcls.__getitem__(self, key)
  File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\werkzeug\datastructures.py", line 442, in __getitem__
    raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'audio_data'
127.0.0.1 - - [11/Jan/2021 06:50:00] "GET /result?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Jan/2021 06:50:00] "GET /result?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [11/Jan/2021 06:50:00] "GET /result?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [11/Jan/2021 06:50:00] "GET /result?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
hello
2021-01-11 06:50:11.906955: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:116] None of the MLIR optimization passes are enabled (registered 2)
There is 78 percent chance that you are trying to get the weather!
127.0.0.1 - - [11/Jan/2021 06:50:13] "POST /result HTTP/1.1" 200 -

如您所見,它首先嘗試使用 GET 方法並返回錯誤。 之后,它嘗試使用 POST 請求,結果在命令行中返回,但從未顯示在瀏覽器中 - 錯誤消息保留在那里。 當我檢查方法是 POST 還是 GET 時,它會使用 GET 執行代碼。 如何讓它接收 POST 請求?

這是我的 python 代碼。

from flask import Flask, render_template, request, redirect, url_for
from werkzeug.utils import secure_filename
import os

from intent_classification import ICModel
from voice_to_text import VTTModel

IC = ICModel()
VTT = VTTModel()

app=Flask(__name__)
app.config['AUDIO_UPLOADS'] = 'audio_file/'

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/result", methods=['POST','GET'])
def result():
    #if(request.method=='POST'):
        print(request.files)
        file = request.files['audio_data']
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['AUDIO_UPLOADS'], filename))
        actual_file = 'audio_file/' + filename
        
        text = VTT.infer(actual_file)
        print(text)
        intent = IC.predict(text)
        print(intent)
        
        os.remove(actual_file)
        
        return render_template("result.html", pred = intent, text = text)
    #else:
        #return redirect(url_for('home'))

if __name__ == "__main__":
    app.run(debug=True)

這是我的 html。

{% extends "base.html" %}

{% block content %}
    <h1 class="font-bold text-5xl text-white mt-5 mb-10">What is on your mind?</h1>
    <div class="flex items-center">
        <img id="record" src="/static/images/record.jpg" alt="record" 
            width="150px" height="150px" class="rounded-xl mx-10" 
            onClick="startRecording()">
        <img id="stop" src="/static/images/stop.jpg" alt="stop" 
            width="150px" height="150px" class="rounded-xl mx-10"
            onClick="stopRecording()">
    </div>
    <form action="/result" method="POST">
        <input type="submit" id="check" 
            class="rounded-lg bg-green-400 hover:bg-green-600 shadow-lg text-xl text-white font-bold my-6 px-16 py-1"
            onclick="upload()" value="Check intent">
    </form>
    <h2 id="prompt" class="font-bold text-3xl text-white my-10" hidden="true">Listening...</h2>
    <div>
        <h3 class="text-3xl text-white mt-10 mb-5">
            You can request the following:
        </h3>
        <ul class="text-xl text-white text-center">
            <li>adding a song to a playlist</li>
            <li>playing music</li>
            <li>booking a table at a restaurant</li>
            <li>getting the weather</li>
            <li>searching for creative work</li>
            <li>rating a book</li>
            <li>searching for a screening event</li>
        </ul>
    </div>
    <script>
        URL = window.URL || window.webkitURL;
        var gumStream;
        var rec;
        var input;
        var AudioContext = window.AudioContext || window.webkitAudioContext;
        var audioContext = new AudioContext;
        var constraints = {
            audio: true,
            video: false
        } 

        var recordButton = document.getElementById("record");
        var stopButton = document.getElementById("stop");
        var checkButton = document.getElementById("check")
        var promptMessage = document.getElementById("prompt");

        recordButton.disabled=false;
        stopButton.disabled=true;
        checkButton.disabled=true;
        promptMessage.hidden = true;

        function startRecording()
        {
            console.log("Recording started.")
            recordButton.disabled = true;
            stopButton.disabled = false;
            promptMessage.hidden=false;

            navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
                console.log("getUserMedia() success, stream created, initializing Recorder.js ..."); 
                gumStream = stream;
                input = audioContext.createMediaStreamSource(stream);
                rec = new Recorder(input, {
                    numChannels: 1
                }) 
                rec.record()
            }).catch(function(err) {
                recordButton.disabled = false;
                stopButton.disabled = true;
                promptMessage.hidden=true;
            });
        }

        function stopRecording()
        {
            console.log("Recording stopped.")
            stopButton.disabled = true;
            recordButton.disabled = false;
            checkButton.disabled = false;
            promptMessage.hidden=true;
            rec.stop();
            gumStream.getAudioTracks()[0].stop();
        }

        function upload()
        {
            console.log("Audio being exported.")
            checkButton.disabled = true;
            var filename = "audio_recording.wav";
            rec.exportWAV(function(blob) {
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function() {
                    if (xhr.readyState == XMLHttpRequest.DONE) {
                        alert(xhr.responseText);
                    }
                }
                var fd = new FormData();
                fd.append('audio_data', blob, filename);
                /* try {
                    let r = await fetch('/result', {method: "POST", body: fd}); 
                    console.log('HTTP response code:',r.status); 
                } catch(e) {
                    console.log(e);
                } */
                var xhr = new XMLHttpRequest();
                xhr.open('POST', '/result', true);
                xhr.send(fd);
            });
        }
    </script>
{% endblock %}

你說的對。
該表單在通過 fetch 或 XMLHttpRequest 進行傳輸之前發送。 您可以使用表單的提交事件來執行您的 javascript function。 調用preventDefault會阻止表單的標准行為。

 <form onsubmit="upload(event)">
   <input type="submit" value="Check intent" />
 </form>
function upload(evt) {
  evt.preventDefault();
  let filename = "audio_recording.wav";
  rec.exportWAV(function(blob) {
    let fd = new FormData();
    fd.append("audio_data", blob, filename);
    fetch("/result", { method: "POST", body: fd })
      .then(resp => { console.log(resp); })
      .catch(err => { console.error(err); });
  });
}

您想如何使用服務器的響應?

當前,您在瀏覽器中使用 ajax function 並以 html 頁面的形式從服務器發送響應。 如果您使用jsonify ,您可以在客戶端使用 JSON 格式的服務器響應。
我還建議您檢查音頻文件是否已傳輸。
以下是一種快速而骯臟的方法。

from flask import jsonify, make_response # , abort

@app.route('/result', methods=['POST'])
def result():
    print(request.files)
    af = request.files.get('audio_data')
    if not af: # if 'audio_data' not in request.files
        # see also abort(400, description='missing audio data')
        return make_response(jsonify(error='missing audio data'), 400)

    # ... process your audio file here ...

    return jsonify(text="lorem ipsum", intent="no-idea");
fetch('/result', { method: "POST", body: fd })
  .then(resp => resp.json())
  .then(data => {
    if ("error" in data) {
      console.error(data.error);
    } else {
      console.log(data);
      let elem;
      if (elem = document.getElementById("output")) elem.innerHTML = data.text;
      if (elem = document.getElementById("intent")) elem.innerHTML = data.intent;
    }
  })
  .catch(err => { console.error(err); });

根據您的要求,您應該查看Web 語音 API

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM