使用Python Flask/Connexion和Swagger在API中处理图像
我试图设置一个非常简单的应用程序。我想将此应用程序创建为fullstack应用程序,作为未来项目的培训。所以我用python编写了一个后端,它通过API(Flask/Connexion)从DB(SQLLite)提供数据。API是通过Swagger记录的。DB应该有一个表,其中每行有2个值: 1.名称 2.图像 我很快就遇到了一个问题:我实际上不知道如何在API中处理图像。因此,我使用占位符创建了备份。到目前为止,图像只是另一个字符串,大部分是空的。一切正常。但现在我希望能够通过API获取图像并将其保存在DB中。我完全不知道怎么做。希望你们中的一个能帮助我 以下是我目前的代码: SqlliteHandler.py使用Python Flask/Connexion和Swagger在API中处理图像,python,image,sqlite,flask,swagger-ui,Python,Image,Sqlite,Flask,Swagger Ui,我试图设置一个非常简单的应用程序。我想将此应用程序创建为fullstack应用程序,作为未来项目的培训。所以我用python编写了一个后端,它通过API(Flask/Connexion)从DB(SQLLite)提供数据。API是通过Swagger记录的。DB应该有一个表,其中每行有2个值: 1.名称 2.图像 我很快就遇到了一个问题:我实际上不知道如何在API中处理图像。因此,我使用占位符创建了备份。到目前为止,图像只是另一个字符串,大部分是空的。一切正常。但现在我希望能够通过API获取图像并将
import sqlite3
conn = sqlite3.connect('sprint_name.db')
c = conn.cursor()
def connect_db():
global conn
global c
conn = sqlite3.connect('sprint_name.db')
c = conn.cursor()
c.execute("CREATE TABLE if not exists sprint_names ( name text, image text)")
def make_db_call(execute_statement, fetch_smth=""):
global c
connect_db()
print(execute_statement)
c.execute(execute_statement)
response = ""
if fetch_smth is "one":
response = transform_tuple_to_dict(c.fetchone())
if fetch_smth is "all":
response_as_tuples = c.fetchall()
response = []
for sug in response_as_tuples:
response.append(transform_tuple_to_dict(sug))
conn.commit()
conn.close()
return response
def transform_tuple_to_dict(my_tuple):
return {"name": my_tuple[0], "image": my_tuple[1]}
def add_name(suggestion):
name = suggestion.get("name")
image = "" if suggestion.get("image") is None else suggestion.get("image")
execute_statement = "SELECT * FROM sprint_names WHERE name='" + name + "'"
print(execute_statement)
alreadyexists = False if make_db_call(execute_statement, "one") is None else True
print(alreadyexists)
if not alreadyexists:
execute_statement = "INSERT INTO sprint_names VALUES ('" + name + "', '" + image + "')"
make_db_call(execute_statement)
def delete_name(suggestion_name):
execute_statement = "DELETE FROM sprint_names WHERE name='" + suggestion_name + "'"
print(execute_statement)
make_db_call(execute_statement)
def delete_all():
make_db_call("DELETE FROM sprint_names")
def get_all_names():
return make_db_call("SELECT * FROM sprint_names", "all")
def get_name(suggestion_name):
print(suggestion_name)
execute_statement = "SELECT * FROM sprint_names WHERE name='" + suggestion_name + "'"
print(execute_statement)
return make_db_call(execute_statement, "one")
def update_image(suggestion_name, suggestion):
new_name = suggestion.get("name" )
new_image = "" if suggestion.get("image") is None else suggestion.get("image")
execute_statement = "UPDATE sprint_names SET name='" + new_name + "', image='" + new_image + "' WHERE name='"\
+ suggestion_name + "'"
make_db_call(execute_statement)
from flask import render_template
import connexion
# Create the application instance
app = connexion.App(__name__, specification_dir='./')
# Read the swagger.yml file to configure the endpoints
app.add_api('swagger.yml')
# Create a URL route in our application for "/"
@app.route('/')
def home():
"""
This function just responds to the browser ULR
localhost:5000/
:return: the rendered template 'home.html'
"""
return render_template('home.html')
# If we're running in stand alone mode, run the application
if __name__ == '__main__':
app.run(port=5000)
RunBackEnd.py
import sqlite3
conn = sqlite3.connect('sprint_name.db')
c = conn.cursor()
def connect_db():
global conn
global c
conn = sqlite3.connect('sprint_name.db')
c = conn.cursor()
c.execute("CREATE TABLE if not exists sprint_names ( name text, image text)")
def make_db_call(execute_statement, fetch_smth=""):
global c
connect_db()
print(execute_statement)
c.execute(execute_statement)
response = ""
if fetch_smth is "one":
response = transform_tuple_to_dict(c.fetchone())
if fetch_smth is "all":
response_as_tuples = c.fetchall()
response = []
for sug in response_as_tuples:
response.append(transform_tuple_to_dict(sug))
conn.commit()
conn.close()
return response
def transform_tuple_to_dict(my_tuple):
return {"name": my_tuple[0], "image": my_tuple[1]}
def add_name(suggestion):
name = suggestion.get("name")
image = "" if suggestion.get("image") is None else suggestion.get("image")
execute_statement = "SELECT * FROM sprint_names WHERE name='" + name + "'"
print(execute_statement)
alreadyexists = False if make_db_call(execute_statement, "one") is None else True
print(alreadyexists)
if not alreadyexists:
execute_statement = "INSERT INTO sprint_names VALUES ('" + name + "', '" + image + "')"
make_db_call(execute_statement)
def delete_name(suggestion_name):
execute_statement = "DELETE FROM sprint_names WHERE name='" + suggestion_name + "'"
print(execute_statement)
make_db_call(execute_statement)
def delete_all():
make_db_call("DELETE FROM sprint_names")
def get_all_names():
return make_db_call("SELECT * FROM sprint_names", "all")
def get_name(suggestion_name):
print(suggestion_name)
execute_statement = "SELECT * FROM sprint_names WHERE name='" + suggestion_name + "'"
print(execute_statement)
return make_db_call(execute_statement, "one")
def update_image(suggestion_name, suggestion):
new_name = suggestion.get("name" )
new_image = "" if suggestion.get("image") is None else suggestion.get("image")
execute_statement = "UPDATE sprint_names SET name='" + new_name + "', image='" + new_image + "' WHERE name='"\
+ suggestion_name + "'"
make_db_call(execute_statement)
from flask import render_template
import connexion
# Create the application instance
app = connexion.App(__name__, specification_dir='./')
# Read the swagger.yml file to configure the endpoints
app.add_api('swagger.yml')
# Create a URL route in our application for "/"
@app.route('/')
def home():
"""
This function just responds to the browser ULR
localhost:5000/
:return: the rendered template 'home.html'
"""
return render_template('home.html')
# If we're running in stand alone mode, run the application
if __name__ == '__main__':
app.run(port=5000)
招摇过市.yml
swagger: "2.0"
info:
description: This is the swagger file that goes with our server code
version: "1.0.0"
title: Swagger REST Article
consumes:
- "application/json"
produces:
- "application/json"
basePath: "/api"
# Paths supported by the server application
paths:
/suggestions:
get:
operationId: SqlliteHandler.get_all_names
tags:
- suggestions
summary: The names data structure supported by the server application
description: Read the list of names
responses:
200:
description: Successful read names list operation
schema:
type: array
items:
properties:
name:
type: string
image:
type: string
post:
operationId: SqlliteHandler.add_name
tags:
- suggestions
summary: Create a name and add it to the names list
description: Create a new name in the names list
parameters:
- name: suggestion
in: body
description: Suggestion you want to add to the sprint
required: True
schema:
type: object
properties:
name:
type: string
description: Name you want to submit
image:
type: string
description: path to the picture of that name
responses:
201:
description: Successfully created name in list
/suggestions/{suggestion_name}:
get:
operationId: SqlliteHandler.get_name
tags:
- suggestions
summary: Read one name from the names list
description: Read one name from the names list
parameters:
- name: suggestion_name
in: path
description: name of the sprint name to get from the list
type: string
required: True
responses:
200:
description: Successfully read name from names list operation
schema:
type: object
properties:
name:
type: string
image:
type: string
put:
operationId: SqlliteHandler.update_image
tags:
- suggestions
summary: Update an image in the suggestion list via the name of the suggestions
description: Update an image in the suggestion list
parameters:
- name: suggestion_name
in: path
description: Suggestion you want to edit
type: string
required: True
- name: suggestion
in: body
schema:
type: object
properties:
name:
type: string
image:
type: string
responses:
200:
description: Successfully updated suggestion in suggestion list
delete:
operationId: SqlliteHandler.delete_name
tags:
- suggestions
summary: Delete a suggestion via its name from the suggestion list
description: Delete a suggestion
parameters:
- name: suggestion_name
in: path
type: string
required: True
responses:
200:
description: Successfully deleted a suggestion from the list
要在SQLITE中保存图像(不建议这样做,最好将图像保存为文件并在DB中保存路径),请将其保存为字节数组(存储类型为BLOB,而不是将列定义为BLOB) 在SQL中,将字节数组指定为十六进制字符串。所以你读了你的图像,并建立了一个十六进制字符串
- 注意到
- 字符串或BLOB的最大长度 定义了SQLite中字符串或BLOB的最大字节数 由预处理器宏SQLITE_MAX_LENGTH执行。此参数的默认值 宏是10亿(10亿或100000000)。你可以 在编译时使用命令行选项提高或降低此值 像这样: -DSQLITE_MAX_LENGTH=123456789当前实现将只支持最长为231-1或2147483647的字符串或BLOB长度。还有一些 诸如hex()之类的内置函数可能在这一点之前就失败了。在里面 对安全敏感的应用程序最好不要试图增加 最大字符串和blob长度。事实上,你最好降低价格 字符串和blob的最大长度在 如果可能的话,也只有几百万 在SQLite的部分插入和选择处理过程中,完成 数据库中每一行的内容都编码为单个BLOB。所以 SQLITE_MAX_LENGTH参数还确定 一行中的字节数 可以在运行时使用 sqlite3限制(db、SQLITE限制长度、大小)接口
- 注意到
- SQL语句的最大长度 SQL语句文本中的最大字节数是有限的 到SQLITE_MAX_SQL_LENGTH,默认为1000000。你可以重新定义 此限制应与SQLITE_MAX_长度和 1073741824 如果SQL语句的长度限制为一百万字节,则 显然,您将无法通过插入数百万字节的字符串 将它们作为文本嵌入INSERT语句中。但是你应该 无论如何,不要那样做。对数据使用主机参数。准备简短的 SQL语句如下: 在表1中插入值(?,?);然后使用sqlite3\u bind\u XXXX() 函数将大字符串值绑定到SQL语句。这个 使用绑定可以避免在 字符串,降低SQL注入攻击的风险。它也在运行 速度更快,因为大字符串不需要作为 很多 SQL语句的最大长度可以在运行时降低 使用sqlite3_limit(db、SQLITE_limit_SQL_LENGTH、size)接口
INSERT INTO mytable (myimage) VALUES (x'fffe004577aabbcc33f1f8');
作为使用表的演示(稍作修改以包含“正确”的列类型BLOB,这没有什么区别):-
结果将是:-
- 注:Navicat用于运行上述文本。BLOB本质上很难显示,因此无法显示。然而,所显示的是,上面显然存储和检索了数据
但是,与上述情况相反,SQLite在某些情况下(平均大小约为100k或更小(可能更大))允许比文件系统更快的访问。好的,谢谢。在DB中保存路径是我的第一个ID,这就是为什么图像的类型是string:D,所以我想我必须在RunBackEnd.py中定义一个上传文件夹,所有上传的图像都存储在这个文件夹中。但是我怎样才能通过API上传它们呢?@itskajo很抱歉,在这方面我帮不了忙,我从来没有使用过Pyhton,更不用说Flask或Swagger ui了。我猜会有一些教程,也许会有帮助。你可以用很多不同的方式处理图像-你想怎么做?应用程序/八位字节流?base64?甚至序列化的numpy数组。。?你是如何到达终点的,你有一个样本图像吗?您可以将它们作为base64字符串安全地保存在数据库中