我目前正在开发WCF流媒体服务。到目前为止,一切都适用于高达2 GB的文件。我已将该服务设置为流服务,并且我将自己的文件分块为5 MB块。但是,大于2 GB的文件(某处有阈值)我总是得到InvalidOperationException
消息Timeouts are not supported on this stream.
我不确定为什么以及抛出此异常的原因。它不认为这是服务器方面的问题,因为每个请求应该是相同的,并且大多数都是有效的。但例外来自生成的代理。所以来源是System.Private.ServiceModel
堆栈追踪:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass0.<CreateGenericTask>b__1(IAsyncResult asyncResult)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Company.OurApp.App.DataService.BaseFile.<DownloadItem>d__59.MoveNext()
这是我的服务器实现:
var response = new GetFileResponse();
using (var impersonation = new Impersonation(request.Domain, request.Username, request.Password))
{
using (Stream fStream = File.OpenRead(request.FullFilePath))
{
fStream.Seek(request.FilePart * request.FilePartSize, SeekOrigin.Begin);
BinaryReader bStream = new BinaryReader(fStream);
var filePart = bStream.ReadBytes(request.FilePartSize);
using (Stream mStream = new MemoryStream(filePart))
{
response.FileByteStream = mStream;
return response;
}
}
}
GetFileResponse如下所示:
[MessageContract]
public class GetFileResponse
{
[MessageBodyMember(Order = 1)]
public Stream FileByteStream { get; set; }
}
这是客户端处理下载的方式(UWP App):
using (Stream f = await StorageFile.OpenStreamForWriteAsync())
{
//Cancelation area - after every async operation if possilble
for (int i = 0; i < sections; i++)
{
token.ThrowIfCancellationRequested();
var response = await client.GetFilePartAsync(request.ConnectionPassword, request.Domain, i, FilePartSize, FullPath, request.Password, request.Username);
token.ThrowIfCancellationRequested();
DownloadProgress = response.FileByteStream.Length;
f.Seek(0, SeekOrigin.End);
await f.WriteAsync(response.FileByteStream, 0, response.FileByteStream.Length);
await f.FlushAsync();
}
}
这是服务web.config:
<system.serviceModel>
<services>
<service behaviorConfiguration="HttpsServiceBehaviour"
name="Company.OurApp.TransportService.DataService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="streamedBinding" contract="Company.OurAppTransportService.IDataService">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HttpsServiceBehaviour">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="streamedBinding" transferMode="Streamed" closeTimeout="10:00:00">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
在生成客户端代理时,我设置了一些超时但没有改变任何内容:
public DataServiceClient GetDataServiceClient(string endpoint = null)
{
var useEndpoint = String.IsNullOrEmpty(endpoint) ? Configuration.ConfigService : endpoint;
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
result.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
//TODO Try to work with timeouts for larges files?
result.SendTimeout = TimeSpan.FromMinutes(5);
result.ReceiveTimeout = TimeSpan.FromMinutes(5);
result.OpenTimeout = TimeSpan.MaxValue;
if (useEndpoint.ToLower().StartsWith("https://"))
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
else
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly;
var client = new DataServiceClient(result, new System.ServiceModel.EndpointAddress(String.Concat(useEndpoint, fixedEndpointSuffix)));
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
if (AppState.IsLoggedIn)
{
client.ClientCredentials.Windows.ClientCredential.UserName = $@"{AppState.Domain}\{AppState.User}";
client.ClientCredentials.Windows.ClientCredential.Password = AppState.Password;
}
return client;
}
知道抛出异常的地点和原因吗?服务器?客户?它来自溪流吗?非常感谢帮助。
答案 0 :(得分:0)
对于遇到同样问题的其他人。我通过使用WCF TraceViewer分析异常来解决它。我还从控制台应用程序调用了服务,以确保它不是UWP问题。问题是我在响应可以到达客户端之前关闭了流。
执行不力:
var response = new GetFileResponse();
using (var impersonation = new Impersonation(request.Domain, request.Username, request.Password))
{
using (Stream fStream = File.OpenRead(request.FullFilePath))
{
fStream.Seek(request.FilePart * request.FilePartSize, SeekOrigin.Begin);
BinaryReader bStream = new BinaryReader(fStream);
var filePart = bStream.ReadBytes(request.FilePartSize);
using (Stream mStream = new MemoryStream(filePart))
{
response.FileByteStream = mStream;
return response;
}
}
}
这个为我修好了:
Stream fStream = File.OpenRead(request.FullFilePath);
long offset = request.FilePart * request.FilePartSize;
fStream.Seek(offset, SeekOrigin.Begin);
BinaryReader bStream = new BinaryReader(fStream);
var filePart = bStream.ReadBytes((int)request.FilePartSize);
Stream mStream = new MemoryStream(filePart);
response.FileByteStream = mStream;
return response;
希望它有所帮助!