我的wcf客户端在尝试从服务下载文件时出现以下错误: “接收到http://mypc-pc/xmlLoadService/Service.svc的HTTP响应时发生错误。这可能是由于服务端点绑定不使用HTTP协议。这也可能是由于服务器中止了HTTP请求上下文(可能是由于服务关闭)。有关详细信息,请参阅服务器日志。“
正在执行的代码是:
System.IO.FileStream fs;
try
{
fs = (System.IO.FileStream)client.Download(@"C:\UploadedFiles\Test.txt");
byte[] arr = new byte[fs.Length];
int read;
do
{
read = fs.Read(arr, 0, arr.Length);
} while (read != arr.Length);
Console.WriteLine(ASCIIEncoding.ASCII.GetString(arr));
Console.ReadLine();
}
这是我的web.config配置:
<bindings>
<basicHttpBinding>
<binding name="basicHTTP" receiveTimeout="00:10:00"
sendTimeout="00:03:00" closeTimeout="00:10:00"
openTimeout="00:03:00" messageEncoding="Mtom"
maxBufferSize="100000" maxReceivedMessageSize="100000"
transferMode="Buffered">
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Service">
<endpoint address="" binding="wsHttpBinding" contract="IService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
<service behaviorConfiguration="mexBehavior"
name="LoadXMLService.XMLOperations">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="basicHTTP"
behaviorConfiguration=""
contract="LoadXMLService.IxmlLoad" />
</service>
</services>
在服务器上调用'download'函数时失败。
更新:据我所知,从跟踪日志中,文件未在服务端打开。
这是应该打开文件的代码,并且在逐步执行时不会抛出任何异常:
public Stream Download( string path )
{
try
{
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
return stream;
}
}
catch (Exception ex)
{
string error = ex.Message;
return null;
}
}
该文件是一个文本文件,里面只有一行。这是跟踪日志:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>524340</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2009-10-04T15:20:22.7770000Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{cb13d023-8122-4199-896c-78684b2461db}" />
<Execution ProcessName="WebDev.WebServer" ProcessID="8104" ThreadID="8" />
<Channel />
<Computer>TONY-PC</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.ServiceOperationExceptionOnReply.aspx</TraceIdentifier>
<Description>Replying to an operation threw a exception.</Description>
<AppDomain>b986c3da-11-128991431145070000</AppDomain>
<Source>System.ServiceModel.Dispatcher.ImmutableDispatchRuntime/48562646</Source>
<Exception>
<ExceptionType>System.ObjectDisposedException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Cannot access a closed file.</Message>
<StackTrace>
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count)
at System.Xml.XmlMtomWriter.WriteXOPBinaryParts()
at System.Xml.XmlMtomWriter.WriteEndElement()
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String startInfo, String boundary, String startUri, Boolean writeMessageHeaders)
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String boundary)
at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)
</StackTrace>
<ExceptionString>System.ObjectDisposedException: Cannot access a closed file.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count)
at System.Xml.XmlMtomWriter.WriteXOPBinaryParts()
at System.Xml.XmlMtomWriter.WriteEndElement()
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String startInfo, String boundary, String startUri, Boolean writeMessageHeaders)
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String boundary)
at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)</ExceptionString>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
<System.Diagnostics xmlns="http://schemas.microsoft.com/2004/08/System.Diagnostics">
<LogicalOperationStack></LogicalOperationStack>
<Timestamp>921505170062</Timestamp>
<Callstack>
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at System.Diagnostics.TraceEventCache.get_Callstack()
at System.Diagnostics.XmlWriterTraceListener.WriteFooter(TraceEventCache eventCache)
at System.Diagnostics.XmlWriterTraceListener.TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, Object data)
at System.Diagnostics.TraceSource.TraceData(TraceEventType eventType, Int32 id, Object data)
at System.ServiceModel.Diagnostics.DiagnosticTrace.TraceEvent(TraceEventType type, TraceCode code, String description, TraceRecord trace, Exception exception, Object source)
at System.ServiceModel.Diagnostics.TraceUtility.TraceEvent(TraceEventType severity, TraceCode traceCode, TraceRecord extendedData, Object source, Exception exception)
at System.ServiceModel.Diagnostics.TraceUtility.TraceEvent(TraceEventType severity, TraceCode traceCode, Object source, Exception exception)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(MessageRpc& rpc, Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</Callstack>
</System.Diagnostics>
</ApplicationData>
</E2ETraceEvent>
答案 0 :(得分:4)
由于您似乎在使用流式响应 - 您的配置如何?你在客户端配置中有这样的东西吗?
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="FileTransferBinding"
transferMode="StreamedResponse" />
</basicHttpBinding>
</bindings>
<client>
<endpoint name="DefaultEndpoint"
address="....."
binding="basicHttpBinding"
bindingConfiguration="FileTransferBinding"
contract="IYourContract" />
</client>
</system.serviceModel>
BindingConfiguration
,其中包含transferMode=Streamed
或transferMode=StreamResponse
binding=basicHttpBinding
和bindingConfiguration=FileTransferBinding
(其中绑定配置的名称与绑定配置声明中的相同)< / LI>
这是你应该拥有的绝对最低限度 - 但如果没有提供关键信息,那只是猜测......
更新:您的问题最常见的是您的绑定配置中没有transferMode="StreamResponse"
。只有拥有此设置,您才能阅读流作为服务电话的响应!
更新2:如果您仍有问题,我强烈建议您配置并启用WCF跟踪 - 将此代码段添加到您的客户端配置中:
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\log\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
它会将跟踪信息写入文件C:\log\traces.svclog
(确保该目录存在),您可以使用服务跟踪查看器(SvcTraceViewer.exe
中的C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\
)检查这些信息
有关详细信息,请查看有关如何配置和设置WCF跟踪的MSDN docs。
更新3:,因为您想要实际返回流(而不是在服务器上关闭它),您应该不将您的流代码放入{{1阻止!
请改为尝试:
using() {...}
您需要在服务器上打开流,并将其保持打开状态并将其返回。确保客户完成阅读后关闭它是客户的工作。
将该代码放在public Stream Download( string path )
{
try
{
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
return stream;
}
catch (Exception ex)
{
string error = ex.Message;
return null;
}
}
块中通常是最佳做法,但在此“服务器打开流并将其返回到客户端”方案中不起作用。
马克