wcf 文件上传的例子网上很多,我也是借鉴别人的示例。wcf 文件下载的示例网上就很少了,不知道是不是因为两者的处理方式比较类似,别人就没有再上传了。在此本人做下记录备忘。
UploadFile.svc.cs public class UploadFile : IUploadFile { /// <summary> /// 服务器地图文件保存路径 /// </summary> private string savePath = @"D:矿车定位上传地图备份"; /// <summary> /// 上传文件 /// </summary> public void UploadFileMethod(FileUploadMessage myFileMessage) { if(!Directory.Exists(savePath))//地图存放的默认文件夹是否存在 { Directory.CreateDirectory(savePath);//不存在则创建 } string fileName = myFileMessage.FileName;//文件名 string fileFullPath = Path.Combine(savePath, fileName);//合并路径生成文件存放路径 Stream sourceStream = myFileMessage.FileData; if (sourceStream == null) { return; } if (!sourceStream.CanRead) { return; } //创建文件流,读取流中的数据生成文件 using (FileStream fs = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write, FileShare.None)) { try { const int bufferLength = 4096; byte[] myBuffer = new byte[bufferLength];//数据缓冲区 int count; while ((count = sourceStream.Read(myBuffer, 0, bufferLength)) > 0) { fs.Write(myBuffer, 0, count); } fs.Close(); sourceStream.Close(); } catch { return; } } } /// <summary> /// 获取文件列表 /// </summary> public string[] GetFilesList() { if(!Directory.Exists(savePath))//判断文件夹路径是否存在 { return null; } DirectoryInfo myDirInfo = new DirectoryInfo(savePath); FileInfo[] myFileInfoArray = myDirInfo.GetFiles("*.zip"); string[] myFileList = new string[myFileInfoArray.Length]; //文件排序 for (int i = 0; i < myFileInfoArray.Length - 1;i++ ) { for (int j = i + 1; j < myFileInfoArray.Length; j++) { if(myFileInfoArray[i].LastWriteTime > myFileInfoArray[j].LastWriteTime) { FileInfo myTempFileInfo = myFileInfoArray[i]; myFileInfoArray[i] = myFileInfoArray[j]; myFileInfoArray[j] = myTempFileInfo; } } } for (int i = 0; i < myFileInfoArray.Length; i++) { myFileList[i] = myFileInfoArray[i].Name; } return myFileList; } /// <summary> /// 下载地图 /// </summary> public Stream DownLoadFile(string fileName) { string fileFullPath = Path.Combine(savePath, fileName);//服务器文件路径 if(!File.Exists(fileFullPath))//判断文件是否存在 { return null; } try { Stream myStream = File.OpenRead(fileFullPath); return myStream; } catch { return null; } } }
IUploadFile.cs [ServiceContract] public interface IUploadFile { /// <summary> /// 上传文件 /// </summary> [OperationContract(Action = "UploadFile", IsOneWay = true)] void UploadFileMethod(FileUploadMessage myFileMessage); /// <summary> /// 获取文件列表 /// </summary> [OperationContract] string[] GetFilesList(); /// <summary> /// 下载文件 /// </summary> [OperationContract] Stream DownLoadFile(string fileName); } [MessageContract] public class FileUploadMessage { [MessageHeader(MustUnderstand = true)] public string FileName; [MessageBodyMember(Order = 1)] public Stream FileData; }
服务器端 web.config 配置文件 <service behaviorConfiguration="TramcarWcfService.UploadFileBehavior" name="TramcarWcfService.UploadFile"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="UploadFileBinding" contract="TramcarWcfService.IUploadFile"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> <basicHttpBinding> <binding name="UploadFileBinding" maxReceivedMessageSize="9223372036854775807" maxBufferSize="2147483647" sendTimeout="00:10:00" transferMode="Streamed" messageEncoding="Mtom"> <security mode="None"/> </binding> </basicHttpBinding>
由于我的wcf是发布的iis上的需要添加下面的节点,用来设置上传文件的限制大小,虽然我上传的文件比较小,我还是想知道上传大文件是怎样配置的。 <system.web><httpRuntime maxRequestLength="2097151" />
客户端上传文件方法 /// <summary> /// 上传文件 /// </summary> public void UploadFileMethod(string fileName,string fileFullPath) { UploadFile_WcfService.FileUploadMessage myFileMessage = new DataProcess.UploadFile_WcfService.FileUploadMessage(); myFileMessage.FileName = fileName;//文件名 using (FileStream fs = File.OpenRead(fileFullPath)) { myFileMessage.FileData = fs; UploadFile_WcfService.IUploadFile myService = myClient.ChannelFactory.CreateChannel(); try { myService.UploadFileMethod(myFileMessage); } catch { } //关闭流 fs.Close(); } }
客户端下载文件方法 isExit = false;//该变量是窗体是否关闭的标志,如果窗体关闭置为true,跳出写文件循环 //下载地图文件保存路径 string saveFilePath = saveFilePathObj.ToString(); //从服务器中获取地图文件流 Stream sourceStream = myUploadFileClass.DownloadFile(fileNameChecked); if (sourceStream != null) { if (sourceStream.CanRead) { using (FileStream fs = new FileStream(saveFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) { const int bufferLength = 4096; byte[] myBuffer = new byte[bufferLength]; int count; while ((count = sourceStream.Read(myBuffer, 0, bufferLength)) > 0) { if (isExit == false) { fs.Write(myBuffer, 0, count); } else//窗体已经关闭跳出循环 { break; } } fs.Close(); sourceStream.Close(); } } }
上面的配置上传一些比较大的文件应该是没有问题了,如果需要下载大文件还需要在客户端的app.config 中设置如下配置,此处的重点是设置transferMode="Streamed"默认是Buffered
,如果是Buffered是无法设置较大的maxReceivedMessageSize="9223372036854775807" <basicHttpBinding> <binding name="BasicHttpBinding_IUploadFile" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="9223372036854775807" messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="90000000" maxArrayLength="90000000" maxBytesPerRead="90000000" maxNameTableCharCount="90000000" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding>