【问题标题】:streaming big file to azure over wcf failed通过 wcf 将大文件流式传输到 azure 失败
【发布时间】:2016-02-16 22:32:00
【问题描述】:

我需要将一个大文件上传到 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 ---

我无法弄清楚为什么会这样。感谢您提供任何帮助或建议。

【问题讨论】:

    标签: c# wcf azure


    【解决方案1】:

    未处理的异常:System.InsufficientMemoryException:失败 分配一个 371848965 字节的托管内存缓冲区。大量的 可用内存可能不足。

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

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

    使用 WCF 操作的消息契约中的 Stream 属性进行传输 大型物体。

    [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>
    

    【讨论】:

    • 感谢您的回答。事实证明,我还需要在控制台应用的 app.config 中设置 maxReceivedMessageSize。
    猜你喜欢
    • 1970-01-01
    • 2018-05-26
    • 2017-05-24
    • 1970-01-01
    • 2014-12-21
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多