我目前正在使用WCF流服務。到目前爲止,對於文件高達2 GB,一切都很好。我已經將該服務設置爲流媒體服務,並且我以5 MB塊自行分割文件。但是,大於2 GB的文件(某處存在閾值),我總是得到一個InvalidOperationException
,並顯示消息Timeouts are not supported on this stream.
我不確定爲什麼以及在何處引發此異常。它不認爲這是一個服務器端問題,因爲每個請求應該是相同的,其中大多數的工作。但例外來自生成的代理。所以源是System.Private.ServiceModel
流大文件WCF超時異常
堆棧跟蹤:
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()
這裏是我的服務器implementaion:
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 = [email protected]"{AppState.Domain}\{AppState.User}";
client.ClientCredentials.Windows.ClientCredential.Password = AppState.Password;
}
return client;
}
任何想法,以及爲什麼拋出異常?服務器?客戶?它來自流?非常感謝幫助。
有沒有辦法推這個? :)以防萬一它丟失了 - 我仍然面臨着錯誤,並會感謝一些幫助。 – Megalomaniac