代码之家  ›  专栏  ›  技术社区  ›  foson

通过IHTTPassynchandler发送文件时出现问题

  •  3
  • foson  · 技术社区  · 15 年前

    我正在使用IHttpHandler调用Web服务,并将结果字节[]作为下载的文件附件返回给客户端。这很好,但是当我尝试将IHttpHandler更改为iHttpAsynchHandler时,会显示“文件下载”对话框,但文件不会开始/完成下载。我做错了什么?

    <%@ 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;
            }
        }
    }
    
    1 回复  |  直到 15 年前
        1
  •  7
  •   Darin Dimitrov    15 年前

    关于代码的几点意见:

    1. EndGetFile BeginGetFile
    2. 你需要通过考试 cb 作为异步回调而不是 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; } 
    }