Problemas para enviar archivos a través de IHttpAsyncHandler
-
06-07-2019 - |
Pregunta
Estoy usando un IHttpHandler para llamar a un servicio web y devolver el byte resultante [] al cliente como un archivo adjunto descargado. Esto funciona bien, pero cuando intenté cambiar el IHttpHandler a un IHttpAsyncHandler, aparece el cuadro de diálogo de descarga del archivo, pero el archivo no comienza / finaliza la descarga. ¿Qué estoy haciendo mal?
<%@ 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;
}
}
}
Solución
Algunas observaciones sobre su código:
- Debe llamar a
EndGetFile
en la misma instancia de servicio en la que llamó aBeginGetFile
- Debe pasar
cb
como AsyncCallBack en lugar deEndProcessRequest
Aquí está el código con estas observaciones tomadas en cuenta:
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; }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow