一. 开发背景
最近单位一个项目,我正在做产品原型,主要是开发一个web应用能够让用户上传个人信息,包括姓名、出生年月之类的,其中尤其是需要上传用户的个人照片(照片格式可能要200k左右),然后还要开发一个桌面应用需要与web服务器通信,获取用户上传的数据然后再进行处理。这里说明下,之所以不做成全web的应用而额外需要开发一个桌面应用程序的原因是:获取到用户信息后需要采用特定的设备进行打印(不是简单的打印机,而是特定的打印设备,涉及到串口通信,只提供C++、C#等Dll来调用),考虑到web客户端(通常是浏览器)很难与硬件打交道(之前有用网页内嵌activeX控件的方式,但是支持不是很好,只能用IE浏览器,而且需要对浏览器做一些配置),因此,权衡再三,打算直接做个额外的桌面应用。由于牵扯到web开发,桌面应用开发(手机app开发后面也会同步跟进),几乎是所谓的“全栈”开发任务,所以颇费了一番功夫。这里主要记录下其中需要解决的交互难点,也为其他的朋友提供一些借鉴,相信大家不管从事web开发还是桌面应用开发都会遇到这类的问题。
二.开发环境说明
(1)由于需要快速开发产品原型,因此选择了目前比较火的基于Python的Django web 框架(不要问我为什么用Python,人生苦短、我用Python)。另外,考虑到我们的项目使用人员都是在windows下开发,所以我开发平台也选择了Windows。
(2)开发工具我选择了Microsoft Visual Studio 2015(VS2015)。宇宙最强IDE,既可以开发C#桌面应用程序,又可以开发Python(好多人喜欢Pycharm,但我觉得在windows下面还是VS2015最好用)
(3)由于数据的交互方并不一致,借鉴web开发目前比较火的前后端分离的方法,后端Django服务器开发采用了Django Restful 风格,这样也方便我们后期进行手机app开发,只要设定好统一的调用接口就好(get,post,put和delete请求)。
操作系统:Windows 7
Python 版本:3.6.1 Django版本:1.11.14
编程IDE: Visual Studio 2015
三.具体步骤
1.服务器端(Django)
1. 创建一个django项目,名字为MyDemo 同时创建一个应用(app)
安装Python包
pip install djangorestframework==3.9.0
在INSTALLED_APPS中添加rest_framework来激活这个前后端分离框架
INSTALLED_APPS = [
'app',
# Add your apps here to enable them
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', #添加这一行
]
在setting.py文件中添加如下设置用于配置图像存放目录
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
在urls.py文件中添加如下配置:
# 媒体文件地址
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2.创建一个简单模型
在app的models.py文件中定义一个简单模型Profile,包括用户姓名和上传的图像
class Profile(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to = 'pic_folder/')
def __str__(self):
return self.name
由于有图像字段,因此需要安装Python的图像处理的库PIL,否则服务器无法处理图像
pip install pillow==5.3.0
运行同步命令,导入模型到数据库中
python manage.py makemigrations
python manage.py migrate
3.创建后台数据
添加模型到后台管理站点
在app目录下创建admin.py文件,然后对模型进行注册,具体如下:
from django.contrib import admin
from .models import Profile
admin.site.register(Profile)
然后创建超级管理员
python manage.py createsuperuser
按照提示输入管理员信息,然后用该账户登录后台。具体的,运行项目
python manage.py runserver 127.0.0.1:8000
(这里如果不熟的话建议先去熟悉下Django框架),
通过浏览器打开后台, http://127.0.0.1:8000/admin
输入管理员账号和密码,然后看到如下信息
在Profiles中增加两条信息,主要是为了上传两张照片
添加两条信息后保存即可。
4.序列化数据
所谓的序列化数据,就是将服务器中的模型数据按照标准的restful风格进行变换以方便restful api接口调用。
在app目录下创建serializers.py文件,文件内容如下:
from rest_framework import serializers
from .models import Profile
class ProfileSerializer(serializers.ModelSerializer):
image = serializers.ImageField(
max_length = None, use_url=True
)
class Meta:
model = Profile
fields = ('name','image')
上述代码中对需要序列号的类Profile进行了接口封装
接下来在views.py文件中定义访问接口
from rest_framework import generics
from .models import Profile
from .serializers import ProfileSerializer
class ProfileListView(generics.ListAPIView):
queryset=Profile.objects.all()
serializer_class=ProfileSerializer
5.设定路径
编辑MyDemo中的urls.py文件 ,添加应用app的url:
urlpatterns = [
url('admin/', admin.site.urls),
# api接口添加
url(r'^app/', include('app.urls', namespace='app')),
]
然后编辑app下的urls.py文件(没有的话创建一个)
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^profiles/$',views.ProfileListView.as_view(),name='profile_list'),
]
至此,可以正常的访问数据了
运行项目,
python manage.py runserver 127.0.0.1:8000
打开浏览器,输入:http://localhost:8000/app/profiles/ 可以得到如下信息:
点击图像对应的网址,可以访问得到图像。至此,我们成功的将django服务器中的字符串和图像数据进行了有效导出,下面就是
关于客户端如何获取数据和解析的问题了。
2.客户端(C# WinForm程序)
打开VS2015,创建一个WinForm程序,添加一个按钮,一个编辑框,一个PictureBox控件,界面如下:
我们想实现的效果:点击按钮,编辑框显示张三,图片控件显示张三的图片
下面看一下具体的代码实现过程。
双击按钮,编辑敲击事件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.IO;
namespace MyDemoClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string GET(string url, Dictionary<String, String> param)
{
if (param != null) //有参数的情况下,拼接url
{
url = url + "?";
foreach (var item in param)
{
url = url + item.Key + "=" + item.Value + "&";
}
url = url.Substring(0, url.Length - 1);
}
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;//创建请求
request.Method = "GET"; //请求方法为GET
HttpWebResponse res; //定义返回的response
try
{
res = (HttpWebResponse)request.GetResponse(); //此处发送了请求并获得响应
}
catch (WebException ex)
{
res = (HttpWebResponse)ex.Response;
}
StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
string content = sr.ReadToEnd(); //响应转化为String字符串
return content;
}
private void button1_Click(object sender, EventArgs e)//按钮的双击事件
{
string msg = GET("http://localhost:8000/app/profiles/",null);
}
}
}
为了解析json字符串,添加包Newtonsoft.Json 可以使用VS2015自带的“管理Nuget工具包”来进行下载和安装
安装完成后添加引用:
using Newtonsoft.Json;
重新编辑按钮响应事件,代码如下:
private void button1_Click(object sender, EventArgs e)
{
string msg = GET("http://localhost:57786/app/profiles/",null);
JArray ja = (JArray)JsonConvert.DeserializeObject(msg);
//取出张三的所有数据
JObject jo = (JObject)ja[0];
textBox1.Text = jo["name"].ToString();
}
到这里我们运行程序,点击按钮,可以得到下面所示内容:
这里,还剩下图像内容,我们只是得到了访问路径,并没有真的得到图像,因此,我们还需要根据路径从服务器下载图像。
完整代码如下:
private void button1_Click(object sender, EventArgs e)
{
string msg = GET("http://localhost:57786/app/profiles/",null);
JArray ja = (JArray)JsonConvert.DeserializeObject(msg);
//取出张三的所有数据
JObject jo = (JObject)ja[0];
textBox1.Text = jo["name"].ToString();
//下面得到图像数据
string myurl = jo["image"].ToString();
System.Net.WebRequest webreq = System.Net.WebRequest.Create(myurl);
System.Net.WebResponse webres = webreq.GetResponse();
using (System.IO.Stream stream = webres.GetResponseStream())
{
pictureBox1.Image = Image.FromStream(stream);
}
}
最终效果图:
到这里,我们成功的在桌面应用程序上得到了Django服务器上的数据。关于如何从桌面应用程序上传和修改服务器信息我后面有时间会继续撰写博客。
下面给个代码连接,通过VS2015可以直接打开和运行
https://download.csdn.net/download/qianbin3200896/10778421