尝试通过 Web api 调用下载文件时如何解决'Server cannot set status after HTTP headers have been sent'错误?



当我使用 web api 调用下载文件时,我可以轻松下载文件。唯一的问题是在我的错误日志中发送 HTTP 标头后,服务器无法设置状态。 抱歉,如果这可能是一个重复的问题,但这里的答案都没有帮助我。

<a href="/api/DownloadDocumentById?documentId=<%=doc.Id %>" download>
<i class="fa fa-download text-primary"></i>
</a>
<HttpGet>
<ActionName("DownloadDocumentById")>
Public Function DownloadDocumentById(documentId As Integer)
Dim document = xxxxxxxx
Dim context = HttpContext.Current
context.Response.ContentType = document.Type
context.Response.OutputStream.Write(document.Content, 0, document.Size)
context.Response.AddHeader("Content-Disposition", Baselib.FormatContentDispositionHeader($"{document.Name}"))
context.Response.AddHeader("Last-Modified", DateTime.Now.ToLongDateString())
context.Response.Flush()
context.Response.End()
Return HttpStatusCode.OK // Have also tried to create a sub without returning a value
End Function

如前所述,我可以轻松下载文档,但是在发送HTTP标头错误后,IIS日志服务器仍然无法设置状态。 再次抱歉,这是一个重复的问题。希望有人能帮助我。

首先,我认为您应该在开始编写实际输出/内容之前添加所有标头。对于缓冲流(这就是我将要建议的),这应该不会有什么区别,并且大多只是语义上的,但是由于应在写入内容之前添加标头(内容始终是最后一个),如果您决定使用未缓冲的流,将来可能会避免类似的问题。

因此,我建议您相应地重新排序代码:

context.Response.ContentType = document.Type
context.Response.AddHeader("Content-Disposition", Baselib.FormatContentDispositionHeader($"{document.Name}"))
context.Response.AddHeader("Last-Modified", DateTime.Now.ToLongDateString())
context.Response.OutputStream.Write(document.Content, 0, document.Size)

现在,如果您使用未缓冲的流,则当您调用OutputStream.Write()时,内容将立即发送到客户端,因此为了在之后设置HTTP结果,您需要确保整个响应都被缓冲,以便在内部请求(操作和控制器)完成执行之前不会发送。这可以通过在输出任何内容之前将Response.BufferOutput设置为True来完成:

context.Response.BufferOutput = True
context.Response.ContentType = document.Type
'The rest of the code...

最后,您需要删除对Response.Flush()Response.End()的调用,因为它们会过早清空缓冲区并在返回状态代码之前将所有内容写入客户端。

新代码:

(...)
context.Response.BufferOutput = True
context.Response.ContentType = document.Type
context.Response.AddHeader("Content-Disposition", Baselib.FormatContentDispositionHeader($"{document.Name}"))
context.Response.AddHeader("Last-Modified", DateTime.Now.ToLongDateString())
Return HttpStatusCode.OK

相关内容

最新更新