c# - 通过 wcf 将大文件流式传输到 azure 失败

标签 c# wcf azure

我需要将一个大文件上传到 Azure 存储。第一步,我尝试通过 wcf 服务将文件上传到 Web 服务文件夹。我按照此链接 Streaming files over WCF 中的步骤操作。我的服务代码:

namespace MilkboxGames.Services
{    
    [ServiceContract]
    public interface IFileUploadService
    {
        [OperationContract]
        UploadResponse Upload(UploadRequest request);
    }

    [MessageContract]
    public class UploadRequest
    {
        [MessageHeader(MustUnderstand = true)]
        public string BlobUrl { get; set; }

        [MessageBodyMember(Order = 1)]
        public Stream data { get; set; }
    }

    [MessageContract]
    public class UploadResponse
    {
        [MessageBodyMember(Order = 1)]
        public bool UploadSucceeded { get; set; }
    }
}

还有

namespace MilkboxGames.Services
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]


    public class FileUploadService : IFileUploadService
    {
        #region IFileUploadService Members

        public UploadResponse Upload(UploadRequest request)
        {                                    
            try
            {                                                                                                        

                string uploadDirectory = System.AppDomain.CurrentDomain.BaseDirectory;

                string path = Path.Combine(uploadDirectory, "zacharyxu1234567890.txt");
                if (File.Exists(path))
                {
                    File.Delete(path);
                }

                const int bufferSize = 2048;
                byte[] buffer = new byte[bufferSize];
                using (FileStream outputStream = new FileStream(path, FileMode.Create, FileAccess.Write))
                {
                    int bytesRead = request.data.Read(buffer, 0, bufferSize);
                    while (bytesRead > 0)
                    {
                        outputStream.Write(buffer, 0, bytesRead);
                        bytesRead = request.data.Read(buffer, 0, bufferSize);
                    }
                    outputStream.Close();
                }

                return new UploadResponse
                {
                    UploadSucceeded = true
                };
            }
            catch (Exception ex)
            {
                return new UploadResponse
                {
                    UploadSucceeded = false
                };
            }
        }

        #endregion
    }
}

Web.config:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>

  <system.web>
    <compilation debug="false" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" executionTimeout="600"    
    maxRequestLength="2097152" />
    <customErrors mode="Off"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="FileUploadServiceBinding" messageEncoding="Mtom" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:15:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00" transferMode="Streamed">
          <security mode="None">
            <transport clientCredentialType="None" />
          </security>  
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="MilkboxGames.Services.FileUploadService" behaviorConfiguration="FileUploadServiceBehavior">
        <endpoint address="" 
            binding="basicHttpBinding" contract="MilkboxGames.Services.IFileUploadService" bindingConfiguration="FileUploadServiceBinding">
        </endpoint>          
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="FileUploadServiceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>

    <directoryBrowse enabled="true"/>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2147483648" />
      </requestFiltering>
    </security>
  </system.webServer>

</configuration>

为了使用此服务,我创建了一个控制台应用程序并将 wcf 服务添加到服务引用中。我注意到服务方法变成了“public bool Upload(string BlobUrl, System.IO.Stream data)”而不是“public UploadResponse Upload(UploadRequest request)”。有人可以向我解释一下为什么吗?

客户端代码:

        string blobUrl = "assassinscreedrevelationsandroid/GT-I9100G/assassinscreedrevelationsandroid.apk";

        string fileName = "C:\\ws_new\\XuConsoleApplication\\XuConsoleApplication\\bin\\Debug\\motutcimac.myar"; 

        bool bUploadBlobResult;

        byte[] buffer = File.ReadAllBytes(fileName);

        Console.WriteLine("Size = " + buffer.Length);

        Stream fileStream = System.IO.File.OpenRead(fileName);

        FileUploadServiceClient objFileUploadServiceClient = new FileUploadServiceClient();

        bUploadBlobResult = objFileUploadServiceClient.Upload(blobUrl, fileStream);

我成功上传了一个 123.8MB 的文件。当我尝试上传 354.6MB 的文件时,出现以下异常:

Unhandled Exception: System.InsufficientMemoryException: Failed to allocate
 a managed memory buffer of 371848965 bytes. The amount of available memory   
may be low. ---> System.OutOfMemoryException: Exception of type 
'System.OutOfMemoryException' was thrown.
    at System.Runtime.Fx.AllocateByteArray(Int32 size)
    --- End of inner exception stack trace ---

我无法弄清楚为什么会发生这种情况。如有任何帮助或建议,我们将不胜感激。

最佳答案

Unhandled Exception: System.InsufficientMemoryException: Failed to allocate a managed memory buffer of 371848965 bytes. The amount of available memory may be low.

上面的消息表明您的应用程序正在耗尽允许的所有内存,为了增加限制,我认为您需要属性“maxReceivedMessageSize”的更大值

同样来自另一个线程( Failed to allocate a managed memory buffer of 134217728 bytes. The amount of available memory may be low ),建议使用流传输模式进行大文件上传。

Use Stream property in message contract of WCF operation to transfer large objects.

[MessageContract]
public class DocumentDescription
{
    [MessageBodyMember(Namespace = "http://example.com/App")]
    public Stream Stream { get; set; }
}
Configure your binding this way

<binding name="Binding_DocumentService" receiveTimeout="03:00:00"
        sendTimeout="02:00:00" transferMode="Streamed" maxReceivedMessageSize="2000000">
    <security mode="Transport" />
</binding>

关于c# - 通过 wcf 将大文件流式传输到 azure 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35444303/

相关文章:

Azure功能无法再通过vnet连接到自己的存储帐户

c# - 在 C# 中继承 List<> 并覆盖构造函数

c# - 如何在 ASP.net MVC 5 中限制对 Controller 操作的访问

asp.net - 如何根据 ASP.NET 成员资格 token 在 wcf Rest 服务上缓存数据

c# - 为什么我们不能在 WCF 中使用抽象类而不是接口(interface)?

c# - CosmosDb 更改提要 : How to set max concurrent calls to 1?

C# 将 long 转换为字符串

c# - 如何阻止应用程序打开

wcf - 使用 WCF REST 服务对 Windows 帐户以外的其他内容进行基本身份验证?

azure cosmos Db "mongorestore"失败,错误为 "Request size is too large"