【问题标题】:How to log file contents in request body of a multipart/form-data request如何在多部分/表单数据请求的请求正文中记录文件内容
【发布时间】:2018-06-10 13:36:22
【问题描述】:

我正在尝试将我的 asp.net Web API 项目中的所有请求记录到一个文本文件中。我正在使用DelegationHandler 功能在我的应用程序中实现日志记录机制,下面是代码sn-p,

public class MyAPILogHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
           // Captures all properties from the request.
            var apiLogEntry = CreateApiLogEntryWithRequestData(request);
            if (request.Content != null)
            {
                    await request.Content.ReadAsStringAsync()
                        .ContinueWith(task =>
                        {
                            apiLogEntry.RequestContentBody = task.Result;
                        }, cancellationToken);
            }

            return await base.SendAsync(request, cancellationToken)
                .ContinueWith(task =>
                {
                    var response = task.Result;

                    // Update the API log entry with response info
                    apiLogEntry.ResponseStatusCode = (int)response.StatusCode;
                    apiLogEntry.ResponseTimestamp = DateTime.Now;

                    if (response.Content != null)
                    {
                        apiLogEntry.ResponseContentBody = response.Content.ReadAsStringAsync().Result;
                        apiLogEntry.ResponseContentType = response.Content.Headers.ContentType.MediaType;
                        apiLogEntry.ResponseHeaders = SerializeHeaders(response.Content.Headers);
                    }   

                    var logger = new LogManager();
                    logger.Log(new LogMessage()
                    {
                       Message = PrepareLogMessage(apiLogEntry),
                       LogTo = LogSource.File
                    });

                    return response;
                }, cancellationToken);
        }
}

上述实现按预期工作,它将所有必需的请求/响应信息记录到文件中。

但是,当我们使用附加的图像进行任何 multipart/form-data POST api 调用时,在记录此请求后,日志文件会变得很大,因为所有图像/二进制内容都被转换为字符串并将其写入文本文件。请在下面找到日志文件内容,

Body: 
----------------------------079603462429865781513947
Content-Disposition: form-data; name="batchid"

22649EEE-3994-4225-AF73-D9A6B659CAE3
----------------------------079603462429865781513947
Content-Disposition: form-data; name="files"; filename="d.png"
Content-Type: image/png

PNG


IHDR    í   %v ¸   sRGB ®Îé   gAMA  ±üa      pHYs  à  ÃÇo¨d  ÿ¥IDATx^ìýX]K¶(
·îsß»ß÷þï{O÷iÛ    Á2âîîîÁe¹âîî,<@   Á$÷w_ÈZó5$Dwvv×}
----------------------------4334344396037865656556781513947
Content-Disposition: form-data; name="files"; filename="m.png"
Content-Type: image/png

PNG


IHDR    í   %v ¸   sRGB ®Îé   gAMA  ±üa      pHYs  à  ÃÇo¨d  ÿ¥IDATx^ìýX]K¶(
·îsß»ß÷þï{O÷iÛ    Á2âîîîÁe¹âîî,<@   Á$÷w_ÈZó5$Dwvv×}

我不想记录请求正文的二进制内容,只记录请求正文文件内容就足够了,例如,

    ----------------------------079603462429865781513947
    Content-Disposition: form-data; name="batchid"

    22649EEE-3994-4225-AF73-D9A6B659CAE3
    ----------------------------079603462429865781513947
    Content-Disposition: form-data; name="files"; filename="d.png"
    Content-Type: image/png

    ----------------------------4334344396037865656556781513947
    Content-Disposition: form-data; name="files"; filename="m.png"
    Content-Type: image/png

您能否建议如何防止记录请求正文的二进制内容并仅记录请求正文的文件内容。

【问题讨论】:

  • 我用一个简单的例子更新了我现有的答案。

标签: c# asp.net asp.net-mvc asp.net-web-api logging


【解决方案1】:

据我所知,您正在实施类似于this 方法的东西。 上传文件时(即请求类型 "multipart/form-data"),其实际内容总是以 "Content-Type: {ContentTypeValue}\r\n\r\ n" 序列,下一个标头以 "\r\n--" 序列开头(如您的日志中所示)。您可以在ReferenceSource 探索有关原始请求数据解析的更多信息。因此,您可以删除有关文件的所有内容(如果存在),例如,通过 RegEx:

内容类型:{ContentTypeOrOctetStream}\r\n\r\n{FileContentBytesToRemove}\r\n

using System.Text.RegularExpressions;
...
string StripRawFileContentIfExists(string input) {
    if(input.IndexOf("Content-Type") == -1)
        return input;
    string regExPattern = "(?<ContentTypeGroup>Content-Type: .*?\\r\\n\\r\\n)(?<FileRawContentGroup>.*?)(?<NextHeaderBeginGroup>\\r\\n--)";
    return Regex.Replace(input, regExPattern, me => me.Groups["ContentTypeGroup"].Value + string.Empty + me.Groups["NextHeaderBeginGroup"].Value);
}
...
//apiLogEntry.RequestContentBody = task.Result;
apiLogEntry.RequestContentBody = StripRawFileContentIfExists(task.Result);

【讨论】:

  • 非常感谢您的支持。我将尝试这种方法并让您知道结果。非常感谢!!!
  • 您可以先使用示例应用程序对其进行测试,方法是使用上述帖子中的现有请求日志作为输入。可能,您需要根据需要调整最终代码。
【解决方案2】:

我建议将huge content 与日志分开。就像您遇到的那样,它只是将日志中的所有内容都搞砸了。在某种程度上禁用日志功能。

我建议你在文件系统中组织那些huge content。像这样:

---request-a/
  |--request-a-body-multi-part1.txt
  |--request-a-body-multi-part2.txt

只需在您的日志中维护一个链接以引用此文件系统路径。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-03
    • 2014-06-01
    • 1970-01-01
    • 2016-06-29
    • 2021-09-18
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    相关资源
    最近更新 更多