Flask 和 JS 之间的通信不顺利



Background

作为制作图像识别AI应用程序的练习, 我正在尝试测试一些用于开发它的工具。

为了制作一个简单的图像识别AI应用程序, 我决定采取以下方法:

  • 使用HTML5的网络摄像头相关API拍摄主体(前端)
  • 使用Python及其一些与ML相关的库来实现此应用程序的核心功能。
  • 使用 JavaScript 的fetch API和 Python 的Flask进行前端和后端之间的通信。

我将要使用的工具将是fetch APIFlaskHTML + JavaScript, 所以我尝试制作一个示例代码来测试这些工具的工作原理。

问题

JavaScript 和 Flask 之间通过 http 的通信不起作用。 问题可能是

  • 无法将图像数据从JavaScript(前端)发送到Flask(服务器)
  • 处理 json 字符串数据有问题。
  • 用于http通信的Flask代码和JavaScript代码有问题

更详细,请查看以下代码。

文件和代码

  • app.py:定义服务器端函数的烧瓶代码。
  • templatesapp.py返回到客户端的文件所在的目录。
  • index.html:相机的HTML + JS代码,并向Flask发送http请求。
  • post.html:只需显示"hello"即可检查前端和服务器之间的通信是否顺利。

[文件组成]

 ├── app.py
 └── templates
 └── index.html
└── post.html

[app.py]

from flask import Flask
from flask import render_template, redirect, send_from_directory, request
from flask import jsonify
app = Flask(__name__)  

@app.route('/')  
def home():
return render_template("index.html");
@app.route("/tmp",methods=['POST'])
def post():
data = request.get_data()
if not data:
return "no data"
else:
return render_template("post.html")


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

[索引.html]

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Camera Test</title>
<style>
canvas, video{
border: 1px solid gray;
}
</style>
</head>
<body>
<h1>HTML5カメラ</h1>
<video id="camera" width="300" height="200"></video>
<canvas id="picture" width="300" height="200"></canvas>
<form>
<button type="button" id="shutter">シャッター</button>
<button type="button" id="btn-send">send</button>
</form>
<audio id="se" preload="auto">
<source src="camera-shutter1.mp3" type="audio/mp3">
</audio>
<script>
function sendServer(url, param){
fetch(url, param)
.then((response)=>{
return response.json();
})
.then((json)=>{
if(json.status){
alert("送信に『成功』しました");
setImage(json.result);    //json.resultにはファイル名が入っている
}
else{
alert("送信に『失敗』しました");
console.log(`json.status${json.status}`)
console.log(json)
console.log(`[error1] ${json.result}`);
}
})
.catch((error)=>{
alert("送信に『失敗』しました");
//console.log(json)
//console.log(json.result)
console.log(`[error2] ${error}`);
});
}

window.onload = () => {
const video  = document.querySelector("#camera");
const canvas = document.querySelector("#picture");
const se     = document.querySelector('#se');
/** カメラ設定 */
const constraints = {
audio: false,
video: {
width: 300,
height: 200,
facingMode: "user"   // フロントカメラを利用する
// facingMode: { exact: "environment" }  // リアカメラを利用する場合
}
};
/**
* カメラを<video>と同期
*/
navigator.mediaDevices.getUserMedia(constraints)
.then( (stream) => {
video.srcObject = stream;
video.onloadedmetadata = (e) => {
video.play();
};
})
.catch( (err) => {
console.log(err.name + ": " + err.message);
});
/**
* シャッターボタン
*/
document.querySelector("#shutter").addEventListener("click", () => {
const ctx = canvas.getContext("2d");
// 演出的な目的で一度映像を止めてSEを再生する
video.pause();  // 映像を停止
se.play();      // シャッター音
setTimeout( () => {
video.play();    // 0.5秒後にカメラ再開
}, 500);
// canvasに画像を貼り付ける
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
});

document.querySelector("#btn-send").addEventListener("click", ()=>{
// Canvasのデータを取得
const pic = canvas.toDataURL("image/png");  // DataURI Schemaが返却される
// 送信情報の設定
const param  = {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({data: pic})
};
const SAVE_URL = "http://localhost:5000/tmp";
// サーバへ送信
console.log(param)

sendServer(SAVE_URL, param);
});
};
</script>
</body>
</html>

[后.html]

<body>
hello
</body>

我现在遇到的确切错误是

  • ** 核心问题可能发生在index.htmlsendServer函数 **
  • ** 没有 json 数据附加到来自 Flask 的 http-response**

怎么了?

任何信息将不胜感激。

编辑

202,当我通过按"发送"按钮发送http请求时弹出的状态代码,因此发送请求(通过POST方法)可能会成功。在这种情况下,有什么问题?我猜sendServer函数实现错误或 json 的处理是错误的。

C:UsersNaokiyaruzo>python app.py
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 955-089-816
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [19/Sep/2021 13:18:59] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [19/Sep/2021 13:19:01] "GET /camera-shutter1.mp3 HTTP/1.1" 404 -
127.0.0.1 - - [19/Sep/2021 13:19:01] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [19/Sep/2021 13:19:47] "POST /tmp HTTP/1.1" 200 -

已编辑 2

作为回答者的建议,我尝试删除JSONStringify并将图像数据直接放入 http 请求的body中,但现在我发现了另一个错误。 [修改]

//index.html
const param  = {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: {data: pic}
};

[新错误]

SyntaxError: Unexpected token o in JSON at position 1

错误位于sendServer函数的.catch部分。

function sendServer(url, param){
fetch(url, param)
.then((response)=>{
return response.json();
})
.then((json)=>{
if(json.status){
alert("送信に『成功』しました");
setImage(json.result);    //json.resultにはファイル名が入っている
}
else{
alert("送信に『失敗』しました");
console.log(`json.status${json.status}`)
console.log(json)
console.log(`[error1] ${json.result}`);
}
})
.catch((error)=>{
alert("送信に『失敗』しました");
//console.log(json)
//console.log(json.result)
console.log(`[error2] ${error}`);
});
}

当您怀疑问题出在 Flask 或 sendServer 端时,我也认为问题出在这两个方面,但我无法确认似乎出了什么问题。所以需要解决一些问题,您能否确认请求是否正在发送以及返回的状态代码(您可以在网络选项卡下从烧瓶调试或浏览器调试中检查)浏览器应该显示尝试发送请求的状态代码。

第一个解决方案

因此,如果状态代码为 404,则请求中有问题,通常是数据或发送的 CORS 应该与请求标头一起传递。我怀疑第二种选择,所以我建议您在代码中添加以下内容并再次尝试发送图像(将端口替换为您要从中发送请求的端口或仅保留本地主机)

#app.py
app = Flask(__name__)
CORS(app,resources={r"/*":{"http://localhost:{port}":"*","http://localhost":"*"}})

第二种解决方案

如果第一个解决方案不起作用并且状态代码仍然是 404,那么问题应该出在发送的数据中。尝试在参数中取出(JSON.stringify),看起来像这样,

//index.html
const param  = {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: {data: pic}
};

最新更新