我正在使用IHttpHandler调用web服务并将生成的byte []作为下载的文件附件返回给客户端.这很好,但是当我尝试将IHttpHandler更改为IHttpAsyncHandler时,文件下载对话框显示,但文件没有开始/完成下
<%@ WebHandler Language="C#" Class="PreviewPDF" %> using System; using System.Web; public class PreviewPDF : IHttpAsyncHandler { public void ProcessRequest(HttpContext context) { } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) { string data = "some data"; using (WebService.RequestService service = new WebService.RequestService()) { AsyncCallback callback = new AsyncCallback(EndProcessRequest); return service.BeginGetFile(data, callback, context); } } public void EndProcessRequest(IAsyncResult result) { HttpContext context = result.AsyncState as HttpContext; byte[] wsoutput; using (WebService.RequestService service = new WebService.RequestService()) { wsoutput = service.EndGetFile(result); } context.Response.ContentType = "application/octet-stream"; context.Response.ContentEncoding = System.Text.Encoding.Unicode; context.Response.AddHeader("Content-Disposition", "attachment; filename=attachment.pdf"); using (System.IO.MemoryStream ms = new System.IO.MemoryStream(wsoutput)) { ms.WriteTo(context.Response.OutputStream); } context.Response.Flush(); } public bool IsReusable { get { return false; } } }关于你的代码的几点评论:
>您需要在名为BeginGetFile的同一服务实例上调用EndGetFile
>您需要将cb作为AsyncCallBack而不是EndProcessRequest传递
以下是考虑到这些评论的代码:
private class State { public HttpContext Context { get; set; } public RequestService Service { get; set; } } public void ProcessRequest(HttpContext context) { throw new NotImplementedException(); } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) { // Don't use using block or it will dispose the service before you can call EndGetFile var state = new State { Service = new RequestService(), Context = context }; // Pass cb here and not EndProcessRequest return state.Service.BeginGetFile(cb, state); } public void EndProcessRequest(IAsyncResult result) { State state = result.AsyncState as State; // Be carefull as this may throw: it is best to put it in a try/finally block // so that you dispose properly of the service byte[] buffer = state.Service.EndGetFile(result); state.Service.Dispose(); state.Context.Response.ContentType = "application/octet-stream"; state.Context.Response.AddHeader("Content-Disposition", "attachment; filename=attachment.pdf"); // Write directly into the output stream, and don't call Flush state.Context.Response.OutputStream.Write(buffer, 0, buffer.Length); } public bool IsReusable { get { return false; } }