Windwos系统部署Flask+AI方案
Flask:web框架
tornado:支持异步高并发,大量http的持久链接
supervisro-win:监控web服务,死掉及重启
srvany:将flask程序注册到系统服务里。便于维护。
一 安装虚拟环境
pip install virtualenv -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
virtualenv ENV
进入虚拟环境脚本目录
激活虚拟环境
activate.bat
二 安装库(安装在虚拟环境中)
安装ultralytics(YoloV8)
pip install ultralytics -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
如果要安装GPU版本torch,需先卸载cpu版本torch。否则可以跳过这一步
pip uninstall torch
pip uninstall torchvision
安装GPU版本Torch
pip install torch-xxx
pip install torchvision-xxx
安装flask 、tornado 、supervisor-win、pyinstaller
pip install flask tornado supervisor-win pyinstaller -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
三 使用lableme进行打标
打包labelme为exe
或者右键选择
四 labelme数据集转yolo数据集格式
flask
from flask import Flask, request
from ultralytics import YOLO
import io
from PIL import Image
app = Flask(__name__)
# 1 加载模型
model = YOLO(r'F:\PycharmProjects\pythonProject\Train\Model\weights\best.pt') # load a pretrained model (recommended for training)
# C# 访问 C# HttpWebRequest http://127.0.0.1:5000/test
@app.route("/test",methods=["GET","POST"])
def api_root():
fileByte = request.get_data()
imageData = io.BytesIO(fileByte)
img = Image.open(imageData)
# 预测图像和训练图像大小一致
results = model.predict(source=img, imgsz=512,
save=False, batch=1) # save plotted images
xyxy_list = []
cls_list =[]
conf_list = []
for result in results:
xyxy = result.boxes.cuda().cpu().numpy().xyxy
cls = result.boxes.cuda().cpu().numpy().cls # Masks object for segmentation masks outputs
conf = result.boxes.cuda().cpu().numpy().conf # Class probabilities for classification outputs
xyxy_list.append(xyxy)
cls_list.append(int(cls))
conf_list.append(int(conf))
res_dict = {"xyxy":xyxy_list,"conf":conf_list,"cls":cls_list}
return str(res_dict)
if __name__ == '__main__':
app.run()
tornado_service.py
# coding=utf-8
import platform
if platform.system() == "Windows":
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from flask_app import app
import logging
# 确定日期格式
DATEFMT = "[%Y-%m-%d %H:%M:%S]"
# 确定日志格式
FORMAT = "%(asctime)s %(thread)d %(message)s"
# 配置日志参数
logging.basicConfig(level=logging.INFO,
format=FORMAT,
datefmt=DATEFMT,
filename=r'.\tornado_log.log')
if __name__ == '__main__':
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()
supervisor.conf
[inet_http_server] ; inet (TCP) server disabled by default
port=127.0.0.1:9001 ; ip_address:port specifier, *:port for all iface
username=admin ; default is no username (open server)
password=123456 ; default is no password (open server)
[supervisord]
logfile=supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
silent=false ; no logs to stdout if true; default false
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
;umask=022 ; (process file creation umask;default 022)
;user=chrism ; (default is current user, required if root)
;identifier=supervisor ; (supervisord identifier, default is 'supervisor')
;directory=%(ENV_TMP) ; (default is not to cd during start)
;nocleanup=true ; (don't clean up tempfiles at start;default false)
;childlogdir=%(ENV_TMP) ; ('AUTO' child log dir, default $TEMP)
;environment=KEY="value" ; (key value pairs to add to environment)
;strip_ansi=false ; (strip ansi escape codes in logs; def. false)
;delaysecs=0.5 ; (delay system processing per seconds; def. 0.5)
; The rpcinterface:supervisor section must remain in the config file for
; RPC (supervisorctl/web interface) to work. Additional interfaces may be
; added by defining them in separate [rpcinterface:x] sections.
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
; The supervisorctl section configures how supervisorctl will connect to
; supervisord. configure it match the settings in either the unix_http_server
; or inet_http_server section.
[supervisorctl]
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris ; should be same as in [*_http_server] if set
;password=123 ; should be same as in [*_http_server] if set
;prompt=mysupervisor ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history ; use readline history if available
; The sample program section below shows all possible program subsection values.
; Create one or more 'real' program: sections to be able to control them under
; supervisor.
[program:theprogramname]
directory = F:\\PycharmProjects\\pythonProject\\
command = F:\\Virtualenv_ENV\\ENV\\Scripts\\python.exe F:\\PycharmProjects\\pythonProject\\tornado_service.py
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; number of processes copies to start (def 1)
;directory=%(ENV_TMP) ; directory to cwd to before exec (def no cwd)
;umask=022 ; umask for process (default None)
;priority=999 ; the relative start priority (default 999)
autostart=true ; start at supervisord start (default: true)
startsecs=10 ; # of secs prog must stay up to be running (def. 1)
startretries=3 ; max # of serial start failures when starting (default 3)
autorestart=true ; when to restart if exited after running (def: unexpected)
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
;stopsignal=QUIT ; signal used to kill process (default TERM)
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
;killasgroup=false ; SIGKILL the UNIX process group (def false)
;user=chrism ; setuid to this UNIX account to run the program
;redirect_stderr=true ; redirect proc stderr to stdout (default false)
stdout_logfile=F:\PycharmProjects\pythonProject\Log\supervisord.log ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
;stdout_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false ; emit events on stdout writes (default false)
;stdout_syslog=false ; send stdout to syslog with process name (default false)
stderr_logfile=F:\PycharmProjects\pythonProject\Log\supervisord.err ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
;stderr_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false ; emit events on stderr writes (default false)
;stderr_syslog=false ; send stderr to syslog with process name (default false)
;environment=A="1",B="2" ; process environment additions (def no adds)
;serverurl=AUTO ; override serverurl computation (childutils)
;cpupriority=normal ; cpu priority; .def normal; others: realtime, high, above, below, idle
;cpuaffinity=0 ; number of cores of cpu is usable by process. def 0 (all cores)
;systemjob=true ; if process die with supervisor. def true
; The sample eventlistener section below shows all possible eventlistener
; subsection values. Create one or more 'real' eventlistener: sections to be
; able to handle event notifications sent by supervisord.
;[eventlistener:theeventlistenername]
;command=path\\eventlistener ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; number of processes copies to start (def 1)
;events=EVENT ; event notif. types to subscribe to (req'd)
;buffer_size=10 ; event buffer queue size (default 10)
;directory=%(ENV_TMP) ; directory to cwd to before exec (def no cwd)
;umask=022 ; umask for process (default None)
;priority=-1 ; the relative start priority (default -1)
;autostart=true ; start at supervisord start (default: true)
;startsecs=1 ; # of secs prog must stay up to be running (def. 1)
;startretries=3 ; max # of serial start failures when starting (default 3)
;autorestart=unexpected ; autorestart if exited after running (def: unexpected)
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
;stopsignal=TERM ; signal used to kill process (default TERM)
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
;killasgroup=false ; SIGKILL the UNIX process group (def false)
;user=chrism ; setuid to this UNIX account to run the program
;redirect_stderr=false ; redirect_stderr=true is not allowed for eventlisteners
;stdout_logfile=a\\path ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
;stdout_events_enabled=false ; emit events on stdout writes (default false)
;stdout_syslog=false ; send stdout to syslog with process name (default false)
;stderr_logfile=a\\path ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
;stderr_events_enabled=false ; emit events on stderr writes (default false)
;stderr_syslog=false ; send stderr to syslog with process name (default false)
;environment=A="1",B="2" ; process environment additions
;serverurl=AUTO ; override serverurl computation (childutils)
; The sample group section below shows all possible group values. Create one
; or more 'real' group: sections to create "heterogeneous" process groups.
;[group:thegroupname]
;programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions
;priority=999 ; the relative start priority (default 999)
; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.
;[include]
;files = relative\\directory\\*.ini
打包
第一步 激活虚拟环境
打包
pyinstaller F:\PycharmProjects\pythonProject1\tornado_service.py
报下面错,不影响使用,等待即可
部署
[inet_http_server] ; inet (TCP) server disabled by default
port=127.0.0.1:9001 ; ip_address:port specifier, *:port for all iface
username=admin ; default is no username (open server)
password=123456 ; default is no password (open server)
[supervisord]
logfile=supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
silent=false ; no logs to stdout if true; default false
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
;umask=022 ; (process file creation umask;default 022)
;user=chrism ; (default is current user, required if root)
;identifier=supervisor ; (supervisord identifier, default is 'supervisor')
;directory=%(ENV_TMP) ; (default is not to cd during start)
;nocleanup=true ; (don't clean up tempfiles at start;default false)
;childlogdir=%(ENV_TMP) ; ('AUTO' child log dir, default $TEMP)
;environment=KEY="value" ; (key value pairs to add to environment)
;strip_ansi=false ; (strip ansi escape codes in logs; def. false)
;delaysecs=0.5 ; (delay system processing per seconds; def. 0.5)
; The rpcinterface:supervisor section must remain in the config file for
; RPC (supervisorctl/web interface) to work. Additional interfaces may be
; added by defining them in separate [rpcinterface:x] sections.
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
; The supervisorctl section configures how supervisorctl will connect to
; supervisord. configure it match the settings in either the unix_http_server
; or inet_http_server section.
[supervisorctl]
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris ; should be same as in [*_http_server] if set
;password=123 ; should be same as in [*_http_server] if set
;prompt=mysupervisor ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history ; use readline history if available
; The sample program section below shows all possible program subsection values.
; Create one or more 'real' program: sections to be able to control them under
; supervisor.
[program:theprogramname]
directory = F:\\Virtualenv_ENV\\ENV4\\Scripts\\dist\\tornado_service\\
command = F:\\Virtualenv_ENV\\ENV4\\Scripts\\dist\\tornado_service\\tornado_service.exe
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; number of processes copies to start (def 1)
;directory=%(ENV_TMP) ; directory to cwd to before exec (def no cwd)
;umask=022 ; umask for process (default None)
;priority=999 ; the relative start priority (default 999)
autostart=true ; start at supervisord start (default: true)
startsecs=10 ; # of secs prog must stay up to be running (def. 1)
startretries=3 ; max # of serial start failures when starting (default 3)
autorestart=true ; when to restart if exited after running (def: unexpected)
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
;stopsignal=QUIT ; signal used to kill process (default TERM)
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
;killasgroup=false ; SIGKILL the UNIX process group (def false)
;user=chrism ; setuid to this UNIX account to run the program
;redirect_stderr=true ; redirect proc stderr to stdout (default false)
stdout_logfile=F:\PycharmProjects\pythonProject\Log\supervisord.log ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
;stdout_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false ; emit events on stdout writes (default false)
;stdout_syslog=false ; send stdout to syslog with process name (default false)
stderr_logfile=F:\PycharmProjects\pythonProject\Log\supervisord.err ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
;stderr_capture_maxbytes=1MB ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false ; emit events on stderr writes (default false)
;stderr_syslog=false ; send stderr to syslog with process name (default false)
;environment=A="1",B="2" ; process environment additions (def no adds)
;serverurl=AUTO ; override serverurl computation (childutils)
;cpupriority=normal ; cpu priority; .def normal; others: realtime, high, above, below, idle
;cpuaffinity=0 ; number of cores of cpu is usable by process. def 0 (all cores)
;systemjob=true ; if process die with supervisor. def true
; The sample eventlistener section below shows all possible eventlistener
; subsection values. Create one or more 'real' eventlistener: sections to be
; able to handle event notifications sent by supervisord.
;[eventlistener:theeventlistenername]
;command=path\\eventlistener ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1 ; number of processes copies to start (def 1)
;events=EVENT ; event notif. types to subscribe to (req'd)
;buffer_size=10 ; event buffer queue size (default 10)
;directory=%(ENV_TMP) ; directory to cwd to before exec (def no cwd)
;umask=022 ; umask for process (default None)
;priority=-1 ; the relative start priority (default -1)
;autostart=true ; start at supervisord start (default: true)
;startsecs=1 ; # of secs prog must stay up to be running (def. 1)
;startretries=3 ; max # of serial start failures when starting (default 3)
;autorestart=unexpected ; autorestart if exited after running (def: unexpected)
;exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
;stopsignal=TERM ; signal used to kill process (default TERM)
;stopwaitsecs=10 ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false ; send stop signal to the UNIX process group (default false)
;killasgroup=false ; SIGKILL the UNIX process group (def false)
;user=chrism ; setuid to this UNIX account to run the program
;redirect_stderr=false ; redirect_stderr=true is not allowed for eventlisteners
;stdout_logfile=a\\path ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10 ; # of stdout logfile backups (0 means none, default 10)
;stdout_events_enabled=false ; emit events on stdout writes (default false)
;stdout_syslog=false ; send stdout to syslog with process name (default false)
;stderr_logfile=a\\path ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10 ; # of stderr logfile backups (0 means none, default 10)
;stderr_events_enabled=false ; emit events on stderr writes (default false)
;stderr_syslog=false ; send stderr to syslog with process name (default false)
;environment=A="1",B="2" ; process environment additions
;serverurl=AUTO ; override serverurl computation (childutils)
; The sample group section below shows all possible group values. Create one
; or more 'real' group: sections to create "heterogeneous" process groups.
;[group:thegroupname]
;programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions
;priority=999 ; the relative start priority (default 999)
; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.
;[include]
;files = relative\\directory\\*.ini
运行
supervisord.exe -c supervisor.conf
导出所需环境
pip freeze > requirements.txt
from flask import Flask, request
from ultralytics import YOLO
import io
from PIL import Image
app = Flask(__name__)
import numpy as np
# [] 转 str
def to_str(var):
return str(list(np.reshape(np.asarray(var), (1, np.size(var)))[0]))[1:-1]
# 1 加载模型
model = YOLO(r'F:\PycharmProjects\pythonProject\Train\Model\weights\best.pt') # load a pretrained model (recommended for training)
# C# 访问 C# HttpWebRequest http://127.0.0.1:5000/test
@app.route("/test",methods=["GET","POST"])
def api_root():
# 获取C#传参
seriesNum = request.args.get('seriesNum')
# 获取C#传递文件流(图像)
fileByte = request.get_data()
imageData = io.BytesIO(fileByte)
# 文件流转图像
img = Image.open(imageData)
# AI模型预测(预测图像和训练图像大小一致)
results = model.predict(source=img, imgsz=512,
save=False, batch=1) # save plotted images
# 确定返回信息列表
xyxy_list = [] # 左上角和右下角坐标
cls_list =[] # 类别列表
conf_list = [] # 置信度
# 遍历一张图像上的所有结果
for result in results:
# 坐标
xyxy = result.boxes.cuda().cpu().numpy().xyxy
# 类别
cls = result.boxes.cuda().cpu().numpy().cls # Masks object for segmentation masks outputs
# 置信度
conf = result.boxes.cuda().cpu().numpy().conf # Class probabilities for classification outputs
# 添加到列表
xyxy = xyxy.tolist()[0] # 去除一个维度
xyxy_list.append(to_str(xyxy))
cls_list.append(str(cls[0]))
conf_list.append(str(conf[0]))
# 取消 []
xyxy_list = ",".join(xyxy_list)
conf_list = ",".join(conf_list)
cls_list = ",".join(cls_list)
# 返回格式
res_dict = {"seriesNum":seriesNum , "content":{"xyxy":xyxy_list,"conf":conf_list,"cls":cls_list}}
return str(res_dict)
if __name__ == '__main__':
app.run()
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestFlaskAPI
{
public class Utils
{
public static string BuildQuery(Dictionary<string, string> dir)
{
string data = null;
string itemValue = null;
for (int i = 0; i < dir.Count; i++)
{
var item = dir.ElementAt(i);//获取字典的下标为i的<key,value>值
var itemKey = item.Key; //获取上面得到的key值
if (i < (dir.Count - 1))
{
itemValue = item.Value + "&";//获取上面得到的value值
}
else
{
itemValue = item.Value;
}
data += itemKey + "=" + itemValue;
}
return data;
}
}
public class http_test
{
/// <summary>
/// post请求只传字典参数
/// </summary>
/// <param name="url"></param>
/// <param name="send_params"></param>
public void POST(string url, Dictionary<string, string> send_params)
{
}
/// <summary>
/// post请求,只传图像
/// </summary>
/// <param name="url"></param>
/// <param name="img_path"></param>
public void POST(string url, string img_path)
{
// 确定上传文件
string filePath = img_path;
byte[] fileContentByte = new byte[1024]; // 文件内容二进制
// 将文件转成二进制
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
fileContentByte = new byte[fs.Length];
fs.Read(fileContentByte, 0, Convert.ToInt32(fs.Length));
fs.Close();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
string boundary = "major";
request.ContentType = "multipart/form-data;boundary=" + boundary;
//定义请求流
Stream myRequestStream = request.GetRequestStream();
myRequestStream.Write(fileContentByte, 0, fileContentByte.Length);
//发送
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//获取返回值
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
Console.WriteLine(retString);
//MessageBox.Show(retString);
// 关闭资源
myStreamReader.Close();
myResponseStream.Close();
}
/// <summary>
/// post请求,传图像和参数
/// </summary>
/// <param name="url"></param>
/// <param name="imgpath"></param>
/// <param name="send_params"></param>
public void POST(string url, string imgpath, Dictionary<string, string> send_params)
{
// 确定上传文件
string filePath = imgpath;
byte[] fileContentByte = new byte[1024]; // 文件内容二进制
// 将文件转成二进制
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
fileContentByte = new byte[fs.Length];
fs.Read(fileContentByte, 0, Convert.ToInt32(fs.Length));
fs.Close();
var postData = Utils.BuildQuery(send_params);//转换成:para1=1¶2=2¶3=3
var postUrl = string.Format("{0}?{1}", url, postData);//拼接url
HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;
request.AllowAutoRedirect = true;
request.Method = "POST";
string boundary = "major";
request.ContentType = "multipart/form-data;boundary=" + boundary;
//定义请求流
Stream myRequestStream = request.GetRequestStream();
myRequestStream.Write(fileContentByte, 0, fileContentByte.Length);
//发送
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//获取返回值
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
Console.WriteLine(retString);
//MessageBox.Show(retString);
// 关闭资源
myStreamReader.Close();
myResponseStream.Close();
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static List<string> GetAllFilePaths(string folderPath)
{
List<string> filePaths = new List<string>();
DirectoryInfo folder = new DirectoryInfo(folderPath);
FileInfo[] files = folder.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo file in files)
{
filePaths.Add(file.FullName);
}
return filePaths;
}
private void button1_Click(object sender, EventArgs e)
{
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("seriesNum", "xxxxxx535342423".ToString());
string url = "http://127.0.0.1:5000/test";
http_test ht = new http_test();
for (int i = 0; i < 99000000000000; i++)
{
// ht.POST(url);
// ht.UploadImage(@"F:\pythonDataset\CatDogDet\images\train\1.jpg");
string folderPath = @"F:\pythonDataset\CatDogDet\images\train";
List<string> filePaths = GetAllFilePaths(folderPath);
foreach (string filePath in filePaths)
{
param["seriesNum"] = filePath;
ht.POST(url, filePath, param);
}
Thread.Sleep(10);
}
}
}
}