在优酷上我想上传一段视频,你有想过会台是怎么实现的吗?这里我就为大家分析一下关于利用WCF上传文件,在WCF没出现之前,我一直使用用WebService来上传文件,我不知道别人为什么要这么做,因为我们的文件服务器和网站后台和网站前台都不在同一个机器,操作人员觉得用FTP传文件太麻烦,我就做一个专门用来上传文件的WebService,把这个WebService部署在文件服务器上,然后在网站后台调用这个WebService,把网站后台页面上传上来的文件转化为字节流传给WebService,然后WebService把这个字节流保存文件到一个只允许静态页面的网站(静态网站可以防止一些脚本木马)。
#T#WebService来上传文件存在的问题是效率不高,而且不能传输大数据量的文件,当然你可以用Wse中的MTOM来传输大文件,有了WCF就好多了,通过使用WCF传递Stream对象来传递大数据文件,但有一些限制:只有BasicHttpBinding、NetTcpBinding和NetNamedPipeBinding支持传送流数据。流数据类型必须是可序列化的Stream或MemoryStream。传递时消息体(MessageBody)中不能包含其他数据。TransferMode的限制和MaxReceivedMessageSize的限制等。
下面具体实现:新建一个WCFService,接口文件的代码如下:
- [ServiceContract]
- publicinterfaceIUpLoadService
- {
- [OperationContract(Action="UploadFile",IsOneWay=true)]
- voidUploadFile(FileUploadMessagerequest);
- }
- [MessageContract]
- publicclassFileUploadMessage
- {
- [MessageHeader(MustUnderstand=true)]
- publicstringSavePath;
- [MessageHeader(MustUnderstand=true)]
- publicstringFileName;
- [MessageBodyMember(Order=1)]
- publicStreamFileData;
- }
定义FileUploadMessage类的目的是因为第三个限制,要不然文件名和存放路径就没办法传递给WCF了,根据第二个限制,文件数据是用System.IO.Stream来传递的接口方法只有一个,就是WCF上传文件,注意方法参数是FileUploadMessage接口实现类文件的代码如下:
- publicclassUpLoadService:IUpLoadService
- {
- publicvoidUploadFile(FileUploadMessagerequest)
- {
- stringuploadFolder=@"C:\kkk\";
- stringsavaPath=request.SavePath;
- stringdateString=DateTime.Now.ToShortDateString()+@"\";
- stringfileName=request.FileName;
- StreamsourceStream=request.FileData;
- FileStreamtargetStream=null;
- if(!sourceStream.CanRead)
- {
- thrownewException("数据流不可读!");
- }
- if(savaPath==null)savaPath=@"Photo\";
- if(!savaPath.EndsWith("\\"))savaPath+="\\";
- uploadFolderuploadFolder=uploadFolder+savaPath+dateString;
- if(!Directory.Exists(uploadFolder))
- {
- Directory.CreateDirectory(uploadFolder);
- }
- stringfilePath=Path.Combine(uploadFolder,fileName);
- using(targetStream=newFileStream(filePath,FileMode.Create,FileAccess.Write,FileShare.None))
- {
- //readfromtheinputstreamin4Kchunks
- //andsavetooutputstream
- constintbufferLen=4096;
- byte[]buffer=newbyte[bufferLen];
- intcount=0;
- while((count=sourceStream.Read(buffer,0,bufferLen))>0)
- {
- targetStream.Write(buffer,0,count);
- }
- targetStream.Close();
- sourceStream.Close();
- }
- }
- }
实现的功能是到指定目录下按照日期进行目录划分,然后以传过来的文件名保存文件。这篇文章最主要的地方就是下面的Web.Config配置:
- <system.serviceModel>
- <bindings>
- <basicHttpBinding>
- <bindingnamebindingname="FileTransferServicesBinding"maxReceivedMessageSize="9223372036854775807"
- messageEncoding="Mtom"transferMode="Streamed"sendTimeout="00:10:00"/>
- </basicHttpBinding>
- </bindings>
- <services>
- <servicebehaviorConfigurationservicebehaviorConfiguration="UploadWcfService.UpLoadServiceBehavior"
- name="UploadWcfService.UpLoadService">
- <endpointaddressendpointaddress=""binding="basicHttpBinding"bindingConfiguration="FileTransferServicesBinding"contract="UploadWcfService.IUpLoadService">
- </endpoint>
- <endpointaddressendpointaddress="mex"binding="mexHttpBinding"contract="IMetadataExchange"/>
- </service>
- </services>
- <behaviors>
- <serviceBehaviors>
- <behaviornamebehaviorname="UploadWcfService.UpLoadServiceBehavior">
- <serviceMetadatahttpGetEnabledserviceMetadatahttpGetEnabled="true"/>
- <serviceDebugincludeExceptionDetailInFaultsserviceDebugincludeExceptionDetailInFaults="false"/>
- </behavior>
- </serviceBehaviors>
- </behaviors>
- </system.serviceModel>