【问题标题】:ContentDispositionHeaderValueIdentityExtensions.IsFileDisposition thows ArgumentNullException: Value cannot be null Parameter name: headerContentDispositionHeaderValueIdentityExtensions.IsFileDisposition thows ArgumentNullException: Value cannot be null 参数名称:header
【发布时间】:2019-08-30 15:45:01
【问题描述】:

我有一个旧版 .Net Framework 客户端,其中有很多无法更改的安装。我需要处理用于将文件上传到服务器的 http post 请求。

以前我们可以使用 HttpContext.Request.Files。但是由于我们现在使用的是 dotnet core,所以我们必须使用 HttpContext.Request.Form.Files。这是抛出一个excaption

“值不能为空。参数名称:header”堆栈跟踪如下

在 Microsoft.Net.Http.Headers.ContentDispositionHeaderValueIdentityExtensions.IsFileDisposition(ContentDispositionHeaderValue 标题)在 Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken 取消令牌)在 Microsoft.AspNetCore.Http.Features.FormFeature.ReadForm() 在 Microsoft.AspNetCore.Http.Internal.DefaultHttpRequest.get_Form()

在github上查看asp dotnet core的源码,我可以在第26行看到确切的问题here

return header.DispositionType.Equals("form-data")
                && (!StringSegment.IsNullOrEmpty(header.FileName) || !StringSegment.IsNullOrEmpty(header.FileNameStar));

我认为这是客户端将标头信息添加到文件而不是请求本身的问题,但是当我添加一些中间件(如下)以将该标头添加到我的请求时,HttpContext.Request。表单仍然抛出异常。我不知道创建时是否引发了此异常,或者我没有正确设置标头,或者这是否是 dotnet 核心中的错误。 github 上有一些未解决的问题来改进错误消息,但没有任何迹象表明他们的代码是问题所在。

我只想“修复”标头,因为我知道对该端点的调用将始终是多部分表单数据,理想情况下使用中间件,因此控制器不必处理它。

中间件:

public class FormDataHeaderRepair
{
    private readonly RequestDelegate _next;

    public FormDataHeaderRepair(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        var headers = context.Request.Headers;
        if (context.Request.Path.ToString().Equals("/api/MyController/Queue", StringComparison.OrdinalIgnoreCase))
        {
            if (context.Request.Headers["Content-Disposition"].Count == 0)
            {
               var cv = new Microsoft.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
               cv.FileName = "request.xml";
               var stringVersion = cv.ToString();
               context.Request.Headers[HeaderNames.ContentDisposition] = stringVersion;
            }
        }

        await _next(context);
    }
}

编辑/更新:将此代码添加到我的控制器,为“theResult”返回“true”,这让我认为 ContentDispositionHeaderValueIdentityExtensions 正在使用其他一些缓存的请求/标头集合,因为这是他们的确切评估代码正在使用...或者他们正在以与此不同的方式检索标头。

var header = HttpContext.Request.GetTypedHeaders().ContentDisposition;
var theResult = header.DispositionType.Equals("form-data") && (!StringSegment.IsNullOrEmpty(header.FileName) || !StringSegment.IsNullOrEmpty(header.FileNameStar));

【问题讨论】:

  • 您是添加中间件作为第一个中间件还是至少在app.UseMvc 之前添加?否则它可能会为时已晚地操纵标题。
  • 我想我在最后添加了它!谢谢,我根本没想过。将尝试并报告回来。编辑:它已经在 MVC 之前。该死的。

标签: c# asp.net-core .net-core


【解决方案1】:

这最终导致发送给我们的请求是手动构建的,而不是使用任何库(因为它是在发布多个像这样的文件显然是一场噩梦的时候开发的)

如果您阅读了基于表单的文件提交规范here,您将看到您有一个边界(您定义为上传中两个文件二进制数据之间的分隔符的一串字符),您还将其添加到请求结束以表明您的上一个文件已完全结束。

在最后一个/最后一个边界上,您必须在边界后用尾随“--”终止它,以表明这是上传的结束。我们的客户端代码没有添加最后一组破折号。这显然是在我们上传到的旧服务器上的 IIS/Full .Net Framework 中处理的,它必须是静默错误,或者只是假设没有更多文件并允许请求通过有效。使用asp dotnet core,情况并非如此,尝试处理时请求失败。

修复确实是在应用程序中添加一个中间件,确保在添加 MVC 之前将其添加到应用程序设置中。

app.RepairMissingFormDataHeaders();
app.UseCors("AllowSpecificOrigin");
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc(routes =>
{
    routes.MapRoute("default", "api/{controller}/{action=Index}/{id?}");
});

基本上,中间件会读取我们请求的最后几个字节,如果它与“预期”字节不匹配,它会在内存中创建一个新的字节数组并将它们添加到位。中间件中还有其他检查,因为只有一个客户端访问此端点,因此我们将其限制在 context.Request.Path 以减少运行次数

//Get a flipped version of what the final bytes should be
var endingBytes = Encoding.UTF8.GetBytes("--\r\n").Reverse().ToArray();
var requiresRepair = false;

var last4Bytes = new byte[4];
//Check if the final bites line up
for (int i = 0; i < 4; i++)
{
    last4Bytes[i] = bytes[bytes.Length - (i + 1)];
}

var lastBytesAsString = System.Text.Encoding.UTF8.GetString(last4Bytes);
Logger.LogInformation($"MIDDLEWARE: Last 4 bytes {lastBytesAsString}");

//Check if the final bites line up
for (int i = 0; i < 4; i++)
{
    if (bytes[bytes.Length - (i + 1)] != endingBytes[i])
    {
        requiresRepair = true;
        break;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 2022-06-10
    • 2011-11-01
    • 1970-01-01
    • 2012-01-05
    • 2021-12-23
    相关资源
    最近更新 更多