用于下载大文件的 Wcf Restful Api 服务 - .Net

Wcf Restful Api service to download large files - .Net

提问人:Harjit 提问时间:3/17/2023 最后编辑:Harjit 更新时间:5/12/2023 访问量:120

问:

我使用 Wcf 服务在 restful api 上创建。我正在使用此服务下载带有流的文件。在 localhost 中它工作正常,但是当我使用 url 从远程浏览器使用它时,它在下载一些数据后停止了。例如,总文件大小为 600MB,在 localhost 中我可以下载所有文件,但是当我从远程浏览器使用它时,它开始下载 (10,20,50,126Mb) 并在两者之间停止并在一段时间后出现网络错误。

在我的代码下方,如果我错过了什么。

服务合同:

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

请求处理程序:

<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

初始化服务:

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>

通过跟踪的异常:

semaphore timeout period has expired
asp.net .NET vb.net WCF-REST

评论


答:

0赞 QI You 3/17/2023 #1

您提到在本地运行是可以的,但是远程设备上有问题。

1.由于设备的原因。我们从 WCF 服务器获取数据的速度很慢,导致服务器在一段时间内没有响应,并最终断开连接。基于此,我认为可以更换设备进行验证。

2.数据在服务器端存储后,使用一个线程将数据移动到另一个内存缓存中,可以合理地说,它只是占用了更多的内存,应该不会影响接收请求的速度,其实除了多打开几个线程之外,我还想移除很多内存, 并伴有大量内存对文件IO写出,造成线程打开延迟。

基于此,我认为使用 using() 及时清理线程是一个很好的方法。

3.您可以尝试在 System.Web 上添加它:<httpRuntimemaxRequestLength="102400" />

4.在初始加载时调用服务脚本: ASP.NET 站点预热

5.将服务上传到 IIS 后,可以检查配置文件是否已更改。

此致敬意

评论

0赞 Harjit 3/17/2023
1)我将通过更改测试环境来尝试它。2)在测试点1时,我还将添加读取流的Using方法。3)由于这是一个 vb.net 应用程序,因此它具有app.config文件,如上所述。4) 如何监控自托管服务上的配置文件更改。
0赞 Harjit 3/18/2023
我尝试更改测试环境,但结果仍然相同。此外,当我尝试下载csv文件时,我可以在get方法中获取数据的json对象,然后在客户端将其转换为csv文件吗?这会是一个好方法吗?get 方法中 json 对象的数据大小是否有任何限制。
0赞 Harjit 3/18/2023
我已经检查了跟踪,发现异常是“信号量超时期限已过期”。当它超时设置为 10 分钟并且在运行 20-30 秒后停止时,这有什么意义吗?
0赞 QI You 3/21/2023
事实上,我认为CSV文件更方便传输。它的形式更简单,占用的空间更少。同时,我认为这个文档可以帮助你更好地解决问题。链接
0赞 Harjit 3/21/2023
如果 transferMode=“Buffered”,则通过增加配额,文件可以正常传输。但不是在流模式下。对于流,异常是“信号量超时期限已过期”