Harjit
Harjit

Reputation: 1

Wcf Restful Api service to download large files - .Net

I have created on restful api using Wcf service. I am downloading files with stream using this service. In localhost it works fine, but when i use this from remote browser using url, then it stopped after downloading some of data. Ex. total file size is 600mb, in localhost i can download all of it, but when i use it from remote browser then it start downloading (10,20,50,126Mb) and stopped in between and gives Network error after sometime.

Below the my codes, if i am missing out something.

Service Contract:

<ServiceContract>
Public Interface IService   
    <OperationContract()>
    <WebGet(UriTemplate:="File/{Param}", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Bare)>
    Function FileDownloadRequest(Param As String) As Stream
End Interface

Request Handler:

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Multiple, UseSynchronizationContext:=False)>
Public Class RequestHandler
    Implements IService

Private Function FileDownloadRequest(Param As String) As Stream Implements IService.FileDownloadRequest
        Dim _FileName As String = RootFolder & "\" & Param
        Try
            ReqLogs.Add("<<-- Download request recieved for " & _FileName)
            '
            'Header Set For CORS
            '
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*")
            If (WebOperationContext.Current.IncomingRequest.Method = "OPTIONS") Then
                WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "*")
                WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "*, Content-Type, Accept")
                WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Max-Age", "1728000")
            End If
            If File.Exists(_FileName) Then
                WebOperationContext.Current.OutgoingResponse.Headers("Content-Disposition") = "attachment; filename=" + "Report Data.csv"
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream"
                WebOperationContext.Current.OutgoingResponse.StatusCode = Net.HttpStatusCode.OK

                Dim _FStream As New FileStream(_FileName, FileMode.Open, FileAccess.Read)
                WebOperationContext.Current.OutgoingResponse.ContentLength = _FStream.Length
                ReqLogs.Add("<<-- Download processing..... ++ " & _FStream.Length.ToString)
                Return _FStream
            Else
                ReqLogs.Add("---- File not found to download !!!")
                Throw New Exception("File not found to download")
            End If
        Catch ex As Exception
            ReqLogs.Add("Download event error: " & ex.Message)
            WebOperationContext.Current.OutgoingResponse.StatusCode = Net.HttpStatusCode.InternalServerError
            Return Nothing
        End Try
    End Function

End Class

Initializing Service:

Private _WcfServer As WebServiceHost

_WcfServer = New WebServiceHost(GetType(RequestHandler), New Uri("http://localhost:6700/"))
Dim _Binding As New WebHttpBinding With {
                    .Name = "IService",
                    .MaxBufferSize = 2147483647,
                    .MaxBufferPoolSize = 2147483647,
                    .MaxReceivedMessageSize = 2147483647,
                    .TransferMode = TransferMode.Streamed,
                    .ReceiveTimeout = New TimeSpan(0, 0, 1, 0, 0),
                    .SendTimeout = New TimeSpan(0, 0, 10, 0, 0)
                }
                _Binding.ReaderQuotas.MaxDepth = 2147483647
                _Binding.ReaderQuotas.MaxStringContentLength = 2147483647
                _Binding.ReaderQuotas.MaxBytesPerRead = 2147483647
                _Binding.ReaderQuotas.MaxArrayLength = 2147483647
                _Binding.ReaderQuotas.MaxNameTableCharCount = 2147483647
                _Binding.Security.Mode = WebHttpSecurityMode.None

                _WcfServer.AddServiceEndpoint(GetType(IService), _Binding, "")
                Dim _ServiceBehavior As New ServiceMetadataBehavior With {
                    .HttpGetEnabled = True
                }
                _WcfServer.Description.Behaviors.Add(_ServiceBehavior)

                _WcfServer.Open()

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        <bindings>
          <basicHttpBinding>
            <binding name="Middleware.IService" transferMode="Streamed" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxReceivedMessageSize="2147483647" >
              <readerQuotas  maxArrayLength="2147483647" maxStringContentLength="2147483647" />
              <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows"></transport>
              </security>
            </binding>
          </basicHttpBinding>
          <wsHttpBinding>
            <binding name="Middleware.IService" messageEncoding="Mtom"/>
          </wsHttpBinding>
        </bindings>
          <!--<behaviors>
            <endpointBehaviors>
              <behavior name="IService">
                <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/>
              </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
              <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
              </behavior>
            </serviceBehaviors>
          </behaviors>-->
        <services>
          <!--<service name="FileHandling.WCFHost.FileManagerService">
            <endpoint address=""
                  binding="webHttpBinding"
                  bindingConfiguration="ServiceWebBindingName"
                  behaviorConfiguration="DefaultRestServiceBehavior"
                  name="FileManagerServiceEndpoint"
                  contract="FileHandling.WCFHost.IFileManagerService"/>
          </service>-->
        </services>
    </system.serviceModel>
</configuration>

Exceptions Through Traces:

semaphore timeout period has expired

Upvotes: 0

Views: 146

Answers (1)

QI You
QI You

Reputation: 518

You mentioned that running locally is okay, but there is a problem on the remote device.

1.Due to the device. The slow speed at which we fetch data from the WCF server causes the server to not respond for a while and finally disconnects. Based on this, I think that the device can be replaced for verification.

2.After the data is stored on the server side, a thread is used to move the data to another memory cache, it is reasonable to say that it only occupies more memory and should not affect the speed of receiving requests, in fact, I want to remove a lot of memory in addition to opening several more threads, and accompanied by a large amount of memory to file IO write out, which causes the delay of thread opening.

Based on this, I think a good way to say to use using() to clean up threads in time.

3.You can try adding it on System.Web:<httpRuntimemaxRequestLength="102400" />

4.Invoke the service script on initial load: ASP.NET Site Warmup

5.When your service is uploaded to IIS, you can check to see if the configuration file has changed.

Best Regards

Upvotes: 0

Related Questions