下面的示例代码将文件流写入Response.Body
在 ASP.NET Core 中间件中不起作用(发出空响应):
public Task Invoke(HttpContext context)
{
context.Response.ContentType = "text/plain";
using (var fs = new FileStream("/valid-path-to-file-on-server.txt", FileMode.Open)
using (var sr = new StreamReader(fs))
{
context.Response.Body = sr.BaseStream;
}
return Task.CompletedTask;
}
任何想法这种直接设置的方法可能有什么问题context.Response.Body
?
注意:管道中的任何下一个中间件都将被跳过,不再进行进一步处理。
Update(另一个例子):一个简单的MemoryStream
分配也不起作用(空响应):
context.Response.Body = new MemoryStream(Encoding.UTF8.GetBytes(DateTime.Now.ToString()));
-
不,你永远不能直接这样做。
注意context.Response.Body
是对对象的引用(HttpResponseStream) 那是之前初始化过它可以在HttpContext
。假设所有字节都写入到这个原始 Stream 中。如果您更改Body
参考(point to) 一个新的流对象context.Response.Body = a_new_Stream
, 原本的Stream
根本没有改变。
另外,如果你查看源代码ASP.NET Core
,你总会找到团队copy最后将包装器流添加到原始主体流,而不是进行简单的替换(除非它们使用模拟流进行单元测试)。例如,SPA 预渲染中间件源代码:
finally
{
context.Response.Body = originalResponseStream;
...
And the ResponseCachingMiddleware源代码:
public async Task Invoke(HttpContext httpContext)
{
...
finally
{
UnshimResponseStream(context);
}
...
}
internal static void UnshimResponseStream(ResponseCachingContext context)
{
// Unshim response stream
context.HttpContext.Response.Body = context.OriginalResponseStream;
// Remove IResponseCachingFeature
RemoveResponseCachingFeature(context.HttpContext);
}
-
作为漫游,您可以copy原始流的字节如下:
public async Task Invoke(HttpContext context)
{
context.Response.ContentType = "text/plain";
using (var fs = new FileStream("valid-path-to-file-on-server.txt", FileMode.Open))
{
await fs.CopyToAsync(context.Response.Body);
}
}
或者如果你愿意hijack原始的HttpResponseStream
使用您自己的流包装器:
var originalBody = HttpContext.Response.Body;
var ms = new MemoryStream();
HttpContext.Response.Body = ms;
try
{
await next();
HttpContext.Response.Body = originalBody;
ms.Seek(0, SeekOrigin.Begin);
await ms.CopyToAsync(HttpContext.Response.Body);
}
finally
{
response.Body = originalBody;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)