2009-10-27 2 views
3

Я использую IHttpHandler для вызова веб-службы и возврата полученного байт [] клиенту в виде загруженного прикрепленного файла. Это прекрасно работает, но когда я попытался изменить IHttpHandler на IHttpAsyncHandler, откроется диалоговое окно загрузки файла, но файл не запускается/не заканчивается загрузкой. Что я делаю не так?Проблема с отправкой файла через 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; 
     } 
    } 
} 

ответ

7

Несколько замечаний о вашем коде:

  1. Вы должны вызвать EndGetFile на том же экземпляре службы, на которую вы назвали BeginGetFile
  2. Вам необходимо пройти 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; } 
} 
Смежные вопросы