WCF实现上传图片功能
Posted 陈胜威
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WCF实现上传图片功能相关的知识,希望对你有一定的参考价值。
初次学习实现WCF winform程序的通信,主要功能是实现图片的传输。
下面是实现步骤:
第一步:
首先建立一个类库项目TransferPicLib,导入wcf需要的引用System.ServiceModel,建立接口ITransferPicService,建立类文件TransferPicService实现ITransferPicService接口。
代码:ITransferPicService
ITransferPicService using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace TransferPicLib { [ServiceContract] public interface ITransferPicService { [OperationContract]//操作契约 Stream GetPic(); [OperationContract] void SendPic(Stream transferPic); } }
代码:TransferPicService
TransferPicService using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TransferPicLib { public class TransferPicService : ITransferPicService { public static Stream PicSource = new MemoryStream(); /// <summary> /// 从服务端下载图片到本地 (上传和下载都是拷贝的过程) /// </summary> /// <returns></returns> public Stream GetPic() { MemoryStream ms = new MemoryStream(); PicSource.Position = 0;//指明从第0位开始拷贝 PicSource.CopyTo(ms);//服务端将客户端的Stream复制一份 ms.Position = 0;//注意如果缺少该条代码接收端将无法显示上传图片 return ms;//然后在返回客户端; } /// <summary> /// 从客户端上传图片到服务端(将客户端的Stream拷贝给服务端的Stream) /// </summary> /// <param name="transferPic"></param> public void SendPic(Stream transferPic) { PicSource.Position = 0; transferPic.CopyTo(PicSource); } } } 这里要使用到app.config配置文件,可以通过建立wcf服务类库生成的模板,直接复制过来,修改所需的参数。
代码:app.config
App.config <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" /> </system.web> <!-- 部署服务库项目时,必须将配置文件的内容添加到 主机的 app.config 文件中。System.Configuration 不支持库的配置文件。--> <system.serviceModel> <services> <service name="TransferPicLib.TransferPicService"> <host> <baseAddresses> <add baseAddress = "http://localhost:8100/transferPic" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- 除非完全限定,否则地址将与上面提供的基址相关 --> <endpoint address="" binding="basicHttpBinding" contract="TransferPicLib.ITransferPicService"> <!-- 部署时,应删除或替换下列标识元素,以反映 用来运行所部署服务的标识。删除之后,WCF 将 自动推断相应标识。 --> <identity> <dns value="localhost"/> </identity> </endpoint> <!-- Metadata Endpoints --> <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 --> <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除--> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息, 请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> <!-- 要接收故障异常详细信息以进行调试, 请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息--> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
第二步:
创建一个控制台程序TransferPicHoset,这个程序主要是启动wcf服务。项目建立完成后首先添加TransferPicLib的引用和using System.ServiceModel的引用。
代码:Program
Program using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using System.Threading.Tasks; using TransferPicLib; namespace TransferPicHose { class Program { static void Main(string[] args) { NetTcpBinding bind = new NetTcpBinding(); bind.MaxBufferSize = 214783647; bind.TransferMode = TransferMode.Streamed; bind.MaxReceivedMessageSize = 214783647; bind.Security.Mode = SecurityMode.None; //超出using 范围程序会自动释放 using (ServiceHost host = new ServiceHost(typeof(TransferPicLib.TransferPicService))) { host.AddServiceEndpoint(typeof(ITransferPicService), bind, "net.tcp://localhost:8100/transferPic");//该地址为宿主地址,和客户端接收端地址保持一致 if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://localhost:8103/transferPic/metadata/"); host.Description.Behaviors.Add(behavior); } host.Opened += delegate { Console.WriteLine("图片程序已成功启动!"); }; host.Open(); Console.ReadLine(); } } } }
此刻如果第一步的配置文件没问题,服务就可以启动了,我在做实验的时候,遇到了地址找不到的错误,最后发现是端口配置错误了,通过看官方的demo发现做wcf程序启动visual studio 需要以管理员的身份启动。暂时不知道为什么要以管理员身启动,不过没什么影响。
现在服务已经完成了,下面我们就可以创建图片上传端与接收端了,这里先建立图片上传项目吧
第三步:
创建一个winform项目winFormUploadDemo,这个窗体主要是实现选择图片,上传图片功能。首先要添加TransferPicLib的引用和using System.ServiceModel的引用
界面布局如下:
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using TransferPicLib; namespace winFormUploadDemo { public partial class UploadForm : Form { string fileName = ""; public UploadForm() { InitializeComponent(); } private void btnBrowser_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); if(openFileDialog.ShowDialog()==DialogResult.OK) { fileName = openFileDialog.FileName; txtPicName.Text = fileName; pictureBox1.Load(fileName); }else { return; } } private void btnUpload_Click(object sender, EventArgs e) { FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); Stream sm = new MemoryStream(); fs.Position = 0; fs.CopyTo(sm); //拷贝完成之后进行上传 EndpointAddress epAddr = new EndpointAddress("net.tcp://localhost:8100/transferPic");//此处也可以用IIS做服务 NetTcpBinding bind = new NetTcpBinding();//绑定方式 bind.MaxBufferPoolSize = 2147483647;//最大缓冲 bind.TransferMode = TransferMode.Streamed;//传输模式为流式处理 bind.MaxReceivedMessageSize = 2147483647;//定义了服务端接收Message的最大长度,防止文件过大 bind.Security.Mode = SecurityMode.None;//安全模式设置为不进行验证; //创建一个工厂 ITransferPicService proxy = ChannelFactory<ITransferPicService>.CreateChannel(bind, epAddr); sm.Position = 0; proxy.SendPic(sm);//WCF客户端调用该方法 把客户端sm上传到服务端去; } } }
此时,图片选择与上传功能就实现了。下面我们创建接收端程序
第四步:
界面如下:窗体上添加一个picturebox用来展示接收到的图片
记得添加TransferPicLib的引用和using System.ServiceModel的引用
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using TransferPicLib; namespace WinFormReceiver { public partial class ReceivedForm : Form { public ReceivedForm() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Thread myThread = new Thread(ShowPic);//创建一个线程 myThread.IsBackground = true;//设置后台线程(防止主程序关闭后,仍在运行) myThread.Start();//启动线程 } public void ShowPic() { #region 同客户端一样,创建WCF客户端 EndpointAddress epAddr = new EndpointAddress("net.tcp://localhost:8100/transferPic"); NetTcpBinding bind = new NetTcpBinding(); bind.MaxBufferPoolSize = 2147483647; bind.TransferMode = TransferMode.Streamed; bind.MaxReceivedMessageSize = 2147483647; bind.Security.Mode = SecurityMode.None; //创建一个通道 ITransferPicService proxy = ChannelFactory<ITransferPicService>.CreateChannel(bind, epAddr); #endregion while (true) { Stream streamFromServer = proxy.GetPic(); //返回一个文件流; MemoryStream ms = new MemoryStream();//滤层流拷贝一份; ms.Position = 0; streamFromServer.CopyTo(ms);//将该文件流拷贝给到ms; if (ms.Length == 0) { System.Threading.Thread.Sleep(300);//300百毫秒执行一次; continue; } Bitmap tn = new Bitmap(ms);//创建一个位图;把ms变成图片; pictureBox1.Image = tn; System.Threading.Thread.Sleep(300);//300百毫秒执行一次;Sleep表示当前线程挂起指定的时间; } } } } 这里我们的代码就完成了
第五步
测试启动我们的项目。
四、运行程序。
1、打开TransferPicHost 文件中bin目录,启动“TransferPicHost.exe”,此时会弹出一个控制台应用程序的窗体,并提示“图片功能已成功启动!”。
2、分别启动发送端和接收端项目程序;
(将“WinFormClient” 或者 “WinFormReceiver” 设为启动项目,并启动另一个项目文件夹bin目录下的“WinFormReceiver.exe”或者“WinFormClient.exe”)
点击发送端“浏览按钮” 进行选择图片,之后点击“上传按钮”。这时,你会发现客户端上传的图片显示在了接收端的窗体上。程序运行成功。
源码地址:https://github.com/dearbeans/Test.git
以上是关于WCF实现上传图片功能的主要内容,如果未能解决你的问题,请参考以下文章