ASP.NET内存文件下载报错:无法在HTTP头发送后设置内容类型
解决ASP.NET中"Server cannot set content type after HTTP headers have been sent"下载文件错误
错误原因
点击RadImageButton触发回发时,页面已经开始向客户端输出内容(比如页面HTML、控件状态信息等),HTTP响应头已发送到浏览器,此时再修改Response的ContentType或添加头信息就会触发该错误。
解决方案
方法一:使用ASHX一般处理程序(推荐,复用性更强)
专门创建处理下载的ASHX文件,避免和页面回发的内容输出冲突:
- 创建
DownloadHandler.ashx文件:
public class DownloadHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { using (MemoryStream memoryStream = new MemoryStream()) { using (TextWriter writer = new StreamWriter(memoryStream)) { writer.WriteLine("Line 1"); writer.WriteLine("Line 2"); writer.WriteLine("Line 3"); writer.Flush(); memoryStream.Position = 0; // 重置流指针到开头,确保能读取到内容 context.Response.ClearContent(); context.Response.ClearHeaders(); context.Response.ContentType = "text/plain"; // TXT文件对应正确的ContentType context.Response.AddHeader("Content-Disposition", "attachment; filename=file.txt"); context.Response.AddHeader("Content-Length", memoryStream.Length.ToString()); memoryStream.WriteTo(context.Response.OutputStream); context.Response.Flush(); context.Response.End(); } } } public bool IsReusable { get { return false; } } }
- 修改ASCX中的RadImageButton,取消回发,直接跳转至处理程序:
<telerik:RadImageButton ID="exportExcel" runat="server" Width="16" Height="16" NavigateUrl="~/DownloadHandler.ashx" AutoPostBack="False"> <Image Url="/images/fs/16x16/excel.gif" /> </telerik:RadImageButton>
方法二:修改回发事件代码,终止页面后续渲染
如果必须保留回发逻辑,调整后台代码,确保响应只输出下载内容:
protected void OnExport(object sender, EventArgs e) { try { using (MemoryStream memoryStream = new MemoryStream()) { using (TextWriter writer = new StreamWriter(memoryStream)) { writer.WriteLine("Line 1"); writer.WriteLine("Line 2"); writer.WriteLine("Line 3"); writer.Flush(); memoryStream.Position = 0; // 重置流指针到开头 Response.ClearContent(); Response.ClearHeaders(); Response.ContentType = "text/plain"; Response.AddHeader("Content-Disposition", "attachment; filename=file.txt"); Response.AddHeader("Content-Length", memoryStream.Length.ToString()); memoryStream.WriteTo(Response.OutputStream); Response.Flush(); Response.End(); // 强制终止页面后续渲染,避免输出其他内容 } } } catch (Exception exception) { usp_ins_error_log errorLog = new usp_ins_error_log(); errorLog.runSP(exception, false); } }
关键注意点
- 写完流后必须重置
memoryStream.Position到0,否则流指针在末尾,写入Response的是空内容 - 使用
using语句管理流对象,确保资源正确释放 - 替换
application/force-download为对应文件类型的标准ContentType,比如Excel xlsx文件用application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
内容的提问来源于stack exchange,提问作者lordblendi
相关产品推荐
相关产品推荐

