修改ASP中的静态文件响应.净的核心

本文关键字:响应 核心 文件 静态 ASP 修改 | 更新日期: 2023-09-27 18:12:50

我用app.UseStaticFiles()在我的应用程序中提供了一堆静态文件。我希望在发送特定HTML文件之前向响应中注入一些额外的标记。我的第一次尝试是在静态文件中间件之前添加这样的中间件:

app.Use(async (context, next) => {
    await next();
    // Modify the response here
});

然而,这不起作用,因为我实际上无法读取读取响应流-它使用了红隼的FrameResponseStream,这是不可读的。

所以,我想我可以用我可以写的MemoryStream代替响应体流:

app.Use(async (context, next) => {
    context.Response.Body = new MemoryStream();
    await next();
    // Modify the response here
});

但是这只会导致请求永远不会完成——它会经历所有的管道阶段,但它甚至不会向浏览器返回任何报头。

那么,我有什么办法可以修改StaticFileMiddleware产生的响应吗?


由于所讨论的HTML文件很小(765字节),所以内存消耗不是问题。但是,任何读取/修改响应的尝试仍然会导致与之前相同的问题(没有返回任何内容)。更明确地说,下面是所做的:

app.Use(async (context, next) => {
    var originalStream = context.Response.Body;
    var bufferStream = new MemoryStream();
    context.Response.Body = bufferStream;
    await next();
    bufferStream.Seek(0, SeekOrigin.Begin);
    if (/* some condition */)
    {
        var reader = new StreamReader(bufferStream);
        var response = await reader.ReadToEndAsync();
        // The response string is modified here
        var writer = new StreamWriter(originalStream);
        await writer.WriteAsync(response);
    }
    else
    {
        await bufferStream.CopyToAsync(originalStream);
    }
});

满足else条件的文件可以正常返回,但是满足if条件的特定文件会产生问题。即使我根本不修改流,它仍然挂起。

修改ASP中的静态文件响应.净的核心

是的,提供的默认流是只读的,因为数据只被缓冲一小会儿,然后刷新到客户端。因此你不能倒带或阅读它。

第二次尝试没有成功,因为原始流从未被处理过。您用MemoryStream完全替换了响应体流,并丢弃了原始请求,因此永远不会向其写入任何内容,客户机将永远等待。

你不能忘记,到客户端的流是在原来的流中,你不能用别的东西代替它。

调用await next()后,必须MemoryStream读取数据,然后将其写入原始流。

app.Use(async (context, next) => {
    var originalStream = context.Response.Body;
    var memoryStream = new MemoryStream();
    context.Response.Body = memoryStream;
    await next();
    // Here you must read the MemoryStream, modify it, then write the 
    // result into "originalStream"
});
<<h3>评论/h3>但是要注意,这个解决方案将把整个响应缓冲到服务器内存中,所以如果您发送大文件,这将显著降低ASP的性能。. NET Core应用程序,特别是如果您提供的文件大小为几兆字节,并且导致更频繁地触发垃圾收集。

这不仅会影响你的静态文件,还会影响你所有的常规请求,因为MVC中间件是在静态文件中间件之后调用的。

如果你真的想在每个请求上修改单个(或一个文件列表),我宁愿建议你在控制器中这样做,并将某些文件路由到那里。请记住,如果静态文件中间件没有找到给定的文件,它将调用链中的下一个文件,直到它到达mvc中间件。

只需在那里设置一个路由,将匹配特定的文件或文件夹并将其路由到控制器。读取控制器中的文件并将其写入响应流或仅返回新蒸汽(使用return File(stream, contentType);

)。