文件上传 WCF WEB API(预览版 6)出错:无法向缓冲区写入超过配置的最大缓冲区大小的字节数:65536

Posted

技术标签:

【中文标题】文件上传 WCF WEB API(预览版 6)出错:无法向缓冲区写入超过配置的最大缓冲区大小的字节数:65536【英文标题】:Error with a file upload WCF WEB API (Preview 6) : Cannot write more bytes to the buffer than the configured maximum buffer size: 65536 【发布时间】:2012-01-30 14:18:30 【问题描述】:

我在使用 WCF Web api 时遇到了真正的问题。

我有一个上传文件并保存到磁盘的简单方法。我似乎设置了所有正确的参数,但是当我尝试上传 2mb 文件时收到上述错误消息。

服务器代码:

public static void RegisterRoutes(RouteCollection routes)

    routes.IgnoreRoute("resource.axd/*pathInfo");
    HttpServiceHostFactory _factory  = new HttpServiceHostFactory();

    var config = new HttpConfiguration() 
     
        EnableTestClient = true, 
        IncludeExceptionDetail = true,
        TransferMode = System.ServiceModel.TransferMode.Streamed,
        MaxReceivedMessageSize = 4194304,
        MaxBufferSize = 4194304    
    ;

    _factory.Configuration = config;

    RouteTable.Routes.Add(new ServiceRoute("api/docmanage", _factory, typeof(WorksiteManagerApi)));

客户:

HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClientHandler.MaxRequestContentBufferSize = 4194304;

var byteArray = 
    Encoding.ASCII.GetBytes(ConnectionSettings.WebUsername + ":" + ConnectionSettings.WebPassword);

HttpClient httpClient = new HttpClient(httpClientHandler);
httpClient.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
httpClient.BaseAddress = new Uri(ConnectionSettings.WebApiBaseUrl);
httpClient.MaxResponseContentBufferSize = 4194304;

...

multipartFormDataContent.Add(new FormUrlEncodedContent(formValues));
multipartFormDataContent.Add(byteArrayContent);

var postTask = httpClient.PostAsync("api/docmanage/UploadFile", multipartFormDataContent);

然后,在服务器上:

[WebInvoke(Method = "POST")]
public HttpResponseMessage UploadFile(HttpRequestMessage request)

    // Verify that this is an html Form file upload request
    if (!request.Content.IsMimeMultipartContent("form-data"))
    
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    

    // Create a stream provider for setting up output streams
    MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider();

    // Read the MIME multipart content using the stream provider we just created.
    IEnumerable<HttpContent> bodyparts = request.Content.ReadAsMultipart(streamProvider);

    foreach (var part in bodyparts)
    
        switch (part.Headers.ContentType.MediaType)
        
            case "application/octet-stream":
                if (part.Headers.ContentLength.HasValue)
                
                    // BLOWS UP HERE:            
                    var byteArray = part.ReadAsByteArrayAsync().Result;

                    if (null == fileName)
                    
                        throw new HttpResponseException(HttpStatusCode.NotAcceptable);
                    
                    else
                    
                        uniqueFileId = Guid.NewGuid().ToString();
                        string tempFilename = Path.GetTempPath() + @"\" + uniqueFileId + fileName;

                        using (FileStream fileStream = File.Create(tempFilename, byteArray.Length))
                        
                            fileStream.Write(byteArray, 0, byteArray.Length); 
                        
                    

                
                break;
        
    

有什么想法吗?我正在使用 web api 的最新预览版....我注意到支持文档中缺少很多内容,但似乎有一些缓冲区限制,我无法找到如何指定或被忽略.... .

【问题讨论】:

发布代码时,请确保其格式尽可能可读。要求人们花时间挑选格式错误的样本是不礼貌的。 您在服务器和客户端上是否有任何配置条目?如果是这样,那么您也可以发布它们 只留下所有配置代码...您可以看到配置参数在创建时(和客户端)传递给服务...。 【参考方案1】:

HttpContent 类的(缺少)文档中未明确说明的一件事是默认内部缓冲区为 64K,因此任何不是流的内容都会在内容超出时抛出您看到的异常64Kb。

解决方法是使用以下方法:

part.LoadIntoBufferAsync(bigEnoughBufferSize).Result();
var byteArray = part.ReadAsByteArrayAsync().Result;

我认为 HttpContent 类的缓冲区的 64K 限制是为了防止服务器上发生过多的内存分配。我想知道您是否会更好地将字节数组内容作为 StreamContent 传递?这样它应该仍然可以工作,而不必增加 HttpContent 缓冲区大小。

【讨论】:

谢谢你,我会在星期一试一试。 谢谢你..把它整理出来。在我回来并重新访问代码之前花了很长时间......可以说我延迟依赖它的功能是有原因的!【参考方案2】:

你是否在 web.config 中设置了 maxRequestLength:

<httpRuntime maxRequestLength="10240" />

【讨论】:

这不是请求端的问题...请求到达服务器正常...唯一的问题发生在代码尝试将内容读入字节数组时...此时指出它违反了缓冲区大小限制,即使在托管服务时已明确设置....感觉它是 wcf 中的一个错误....【参考方案3】:

几天来,我在 WCF WinAPI 上遇到了类似的问题,我试图发布一个 12Mb 的文件,但我不知道发生了什么。我的服务器端是托管在 IIS 中的 WCF 服务;我的问题不是 WCF 设置,而是 Toni 提到的。在 IIS 中托管时,请记住增加此设置。 MS 文档指出默认值为 4Mb,这解释了为什么我可以发布 400Kb 的文件。

希望这可以帮助遇到同样问题的其他人。

【讨论】:

以上是关于文件上传 WCF WEB API(预览版 6)出错:无法向缓冲区写入超过配置的最大缓冲区大小的字节数:65536的主要内容,如果未能解决你的问题,请参考以下文章

尝试将 WCF 应用程序上传到服务器时出错

官宣 .NET 6 预览版 6

创建API服务最小只要4行代码!!!尝新体验ASP.NET Core 6预览版本中的最小Web API(minimal APIS)新特性

文件上传(无预览模式版)

REST API 有啥更好的选择? WCF Web API (Preview 4) 或 OpenRasta 还是其他?

使用 Angular 6 将文件上传到 Web Api C#