用Restful方式调用WCF进行上传下载

在前面几篇文章中,分别就WCF如何与Ajax交互,如何返回json数据给Ajax,如何为ExtJs控件提供数据,如何用Http的访问方式异步调用Restful的WCF服务,本文着重讲述如何用Restful方式调用WCFl进行文件的上传和下载。在前面的文章中,曾经写过Restful的WCF支持两种格式的请求和响应的数据格式:1)XML 2) JSON。事实上WCF不光支持上述两种格式,它还支持原生数据(Raw,来源于Carlos' blog)。这样一来,WCF的Restful方式实际上支持任意一种格式的,因为原生的即表明可以是任意一种格式,WCF从客户端到服务端,从服务端到客户端都会保持这种数据的原来的数据格式。通过查阅MSDN中WebMessageEncodingBindingElement 类的说明:也能找到上述的论证

首先总结一下如何在Restful的WCF的服务端和客户端传递原生的数据(Raw),在WCF中,返回值或者参数为System.IO.Stream或者System.IO.Stream的派生类型的时候,加配上HTTP请求和Restful服务操作响应消息中的ContentType,便能实现原生数据的传输。

下面通过一个上传和下载图片文件的项目示例来演示如上的结论。

第一步:在VS2008中,创建一个解决方案:WcfBinaryRestful,包括四个项目:如下图所示:

其中各个项目的说明如下表所述:

项目名称

说明

WcfBinaryRestful.Contracts

WCF服务的契约部分

WcfBinaryRestful.Service

WCF服务具体实现部分

WcfBinaryRestful.Host

WCF服务的Console程序的承载程序

WcfBinaryRestful.Client

客户端

 
第二步:在WcfBinaryRestful.Contracts中创建并设计服务契约IService.cs,代码如下:

IService.cs

其中ReadImg方法用于提供jpg图片文件,供客户端下载,而ReceiveImg用于接收客户端上传的jpg图片

第三步:在WcfBinaryRestful.Service项目中创建并设计服务具体实现类:Service.cs

Service.cs

第四步:用配置的方式,创建服务承载项目:WcfBinaryRestful.Host。并使得服务可以用Restful方式访问。

Host.cs

Host.cs

App.config

App.config

第五步:实现客户端程序

Form1.cs

 

Form1.cs

设置好多启动项目调试后,调试,出现如下的运行界面:

1.服务承载程序运行界面图:

2.客户端运行界面图:

点击开始下载按钮,选择一个下载文件的保存位置,等待一会后,会提示下载成功,如下图所示:

打开刚才选择下载文件的保存位置,便能发现已经成功下载了jpg的图片文件:

当然顺便还可以温习一下如何异步调用Restful的WCF服务,点击取消下载可以停止下载,不再多说

点击开始上传,选择一个要上传的jpg图片,等待几秒钟,便能收到上传成功的对话框,如下图所示:

找到服务承载程序所在目录,便能看到上传的jpg图像文件:

示例项目文件:

作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2008-07-14 22:27 Robin Zhang 阅读(7457) 评论(33) 编辑 收藏

 回复 引用 查看   
#1楼 2008-07-14 22:47 阿滨       
不错.
我只看看,不说话
 回复 引用 查看   
#3楼 2008-07-14 23:45 赖文华(SWPU小赖)      
学习学习!谢谢!
 回复 引用 查看   
#4楼 2008-07-15 08:32 高海东      
谢谢楼主分享,这个在bs结构上一样实现吧
 回复 引用   
#5楼 2008-07-15 08:44 t-mac[未注册用户]
请解释一下名词restful..
 回复 引用 查看   
#6楼[楼主] 2008-07-15 09:01 jillzhang      
@阿滨
@赖文华(SWPU小赖)
多谢支持

 回复 引用 查看   
#7楼[楼主] 2008-07-15 09:11 jillzhang      
@t-mac
呵呵,可能我的标题有些问题
如果是
用restful方式调用wcf进行上传下载
会更好一些,当时没有组织好
抱歉

 回复 引用 查看   
#8楼 2008-07-15 09:28 雅阁布      
非常感谢分享!!!
 回复 引用 查看   
#9楼[楼主] 2008-07-15 09:40 jillzhang      
@高海东
是一样能够实现的,但bs有bs的好处,当然也有其不足
一个服务可以承载很多种不同的业务逻辑,而b/s下一个页面恐怕原则上只能承载一种,这是区别
服务这个,正手可以提供类似服务,翻过来还可以供其他应用程序消费。一箭双雕了吧
b/s恐怕不太好实现
当然b/s发展更为成熟,使用方式更为灵活,但服务是建立在其之上的,必然也会取其精华,所以也能享受b/s页面中绝大多数好处

 回复 引用 查看   
#10楼 2008-07-15 13:59 瑞克梅塔      
来晚了,顶一下,以后慢慢看
 回复 引用 查看   
#11楼 2008-07-16 22:04 coollzh      
好像有点bug,上传大图片有问题
 回复 引用 查看   
#12楼[楼主] 2008-07-17 09:26 jillzhang      
@coollzh
大文件上传的确可能发现问题,wcf的请求长度是有限制的,可能需要更改配置和超时时长

 回复 引用 查看   
#13楼[楼主] 2008-07-17 09:31 jillzhang      
@coollzh
你上传失败的图片有多大?

 回复 引用 查看   
#14楼[楼主] 2008-07-17 09:43 jillzhang      
如果想要上传比较大(太大的也不行)的文件,需要设置WebHttpBinding的MaxReceivedMessageSize,这个属性默认是65536字节,可将其变大,如果文件过于大的话还有可能引发超时错误,解决的办法是设置ReceiveTimeOut,默认是10分钟,也可以调大

 回复 引用 查看   
#15楼 2008-07-24 16:49 阿滨       
上传大文件可以看下我的一张博文
 回复 引用 查看   
#16楼 2008-12-08 10:33 蓉青姚      
你好老大,
后面几篇示例项目文件 都没提供下载吗?
其他的都几乎下载,这几篇不能下,
感觉小了什么

 回复 引用   
#17楼 2008-12-10 11:53 gattaca[未注册用户]
請問有關於REST WCF發送串流視頻的問題!

原本在WebService(asmx)中有Context.Response可以while迴圈持續寫入視訊串流資料
===========================
[WebMethod]
public void getLiveView()
{
...
while (DateTime.Now < playEndTime)
{
byte[] frame = getOneFrame();
Context.Response.BinaryWrite(frame);
Context.Response.Flush();
Thread.Sleep(100);
}
...
}
===========================

但是在REST WCF中卻沒有相對應的方式,
WebOperationContext.Current.OutgoingResponse無法BinaryWrite與Flush,
請問在REST WCF中有類似的方式嗎?

 回复 引用   
#18楼 2008-12-11 09:13 gattaca[未注册用户]
得到解答了!
沿用原來的即可
System.Web.HttpContext.Current.Response

 回复 引用   
#19楼 2008-12-11 18:23 gattaca[未注册用户]
對不起...我錯了,
System.Web.HttpContext.Current只會得到null

 回复 引用 查看   
#20楼[楼主] 2008-12-12 09:23 jillzhang      
@gattaca
Web Service中能做,怎么做大部分都被WCF沿承下来了

 回复 引用 查看   
#21楼 2009-05-08 12:32 chinajuanbob      
请问System.IO.Stream的资源会自动释放吗?
 回复 引用   
#22楼 2009-09-29 20:43 冰封123[未注册用户]
ReceiveImg(System.IO.Stream stream) 方法如果我要加个保存时的文件名,怎么传入?请问
 回复 引用 查看   
#23楼 2009-09-29 21:15 chinajuanbob      
引用冰封123:ReceiveImg(System.IO.Stream stream) 方法如果我要加个保存时的文件名,怎么传入?请问

WebOperationContext.Current.IncomingRequest是一个IncomingWebRequestContext,其中包括一Headers属性,是WebHeaderCollection,所以我猜是不是直接在HTTP头部写些属性就得了。进而对于OutgoingWebResponseContext是不是写一个Content-Disposition字段就能实现保存名称了?
手头没有资源,麻烦谁实践一下并分享结果,先谢过~

 回复 引用   
#24楼 2009-09-29 21:29 冰峰111[未注册用户]
@chinajuanbob
可以实现,是不是可以理解为BS中的web页面的请求里的header呢?

 回复 引用 查看   
#25楼 2009-09-29 21:56 chinajuanbob      
引用冰峰111:
@chinajuanbob
可以实现,是不是可以理解为BS中的web页面的请求里的header呢?

OutgoingWebResponseContext那个也试啦?我是这么理解的,看大牛们怎么说吧

 回复 引用   
#26楼 2009-12-09 11:26 king123456[未注册用户]
很好
 回复 引用 查看   
#27楼 2010-05-13 16:07 胡枫      
蛮好的。不过winform我有点不熟悉,可以发一下源码学习一下吗?hackhu@gmail.com 谢谢楼主。
 回复 引用 查看   
#28楼 2010-09-02 14:59 huiGee      
楼主,我找你讲解的写了一个,可是我的下载的文件都是0字节的。上传的文件找不到,也没有报错,报异常。有没源码Demo发一个看下。wph1129@sohu.com 谢谢!
 回复 引用 查看   
#29楼 2010-11-26 16:30 天涯人      
不能下载啊
 回复 引用 查看   
#30楼 2011-03-03 14:43 Rollo Geng      
这个怎么没有下载了呢,希望下到代码!
 回复 引用 查看   
#31楼 2011-06-09 15:57 翔如飞飞      
主要代码LZ已经贴到BLOG了,还是自己手动实现下吧
引用Rollo Geng:这个怎么没有下载了呢,希望下到代码!

引用天涯人:不能下载啊

主要代码LZ已经贴到BLOG了,还是自己手动实现下吧

 回复 引用 查看   
#32楼 2011-06-20 22:09 硅谷之浪子      
引用jillzhang:<span style="color: #ff0000">如果想要上传比较大(太大的也不行)的文件,需要设置WebHttpBinding的MaxReceivedMessageSize,这个属性默认是65536字节,可将其变大,如果文件过于大的话还有可能引发超时错误,解决的办法是设置ReceiveTimeOut,默认是10分钟,也可以调大</span><br />

你说的“太大的也不行”,是不是指太大的文件就算ReceiveTimeOut设置的再大也不行?
顺便再请教一下,你的程序除了在WINFORM外,在ASP.NET可以用吗?

 回复 引用 查看   
#33楼 2011-11-08 09:23 风的传说      
我是来受教的,呵呵