Detener un flujo de datos antes del final del archivo

En mi aplicación Silverlight necesito descargar archivos grandes. Actualmente estoy transmitiendo estos datos desde una matriz de bytes llamando a una página ASPX en el mismo servidor que aloja la aplicación Silverlight. El ASPX Page_Load() el método se ve así:

protected void Page_Load(object sender, EventArgs e)
{
  // we are sending binary data, not HTML/CSS, so clear the page headers
  Response.Clear();
  Response.ContentType = "Application/xod";

  string filePath = Request["file"];  // passed in from Silverlight app

  //  ...

  using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  {
    // send data 30 KB at a time
    Byte[] t = new Byte[30 * 1024];

    int bytesRead = 0;
    bytesRead = fs.Read(t, 0, t.Length);
    Response.BufferOutput = false;

    int totalBytesSent = 0;

    Debug.WriteLine("Commence streaming...");
    while (bytesRead > 0)
    {
      // write bytes to the response stream
      Response.BinaryWrite(t);

      // write to output how many bytes have been sent
      totalBytesSent += bytesRead;
      Debug.WriteLine("Server sent total " + totalBytesSent + " bytes.");

      // read next bytes
      bytesRead = fs.Read(t, 0, t.Length);
    }
  }

  Debug.WriteLine("Done.");

  // ensure all bytes have been sent and stop execution
  Response.End();
}

Desde la aplicación Silverlight, simplemente entrego el uri al objeto que se lee en la matriz de bytes:

Uri uri = new Uri("https://localhost:44300/TestDir/StreamDoc.aspx?file=" + path);

Mi pregunta es ... ¿Cómo detengo esta transmisión si el usuario cancela? Como está ahora, si el usuario selecciona otro archivo para descargar, la nueva transmisión comenzará y la anterior continuará transmitiéndose hasta que se complete.

No puedo encontrar una manera de cancelar la transmisión una vez que se ha iniciado.

Cualquier ayuda es muy apreciada.

-cott

preguntado el 27 de agosto de 11 a las 20:08

Aparte de cualquier otra cosa, siempre estás asumiendo que la llamada de lectura llena el búfer, porque luego estás escribiendo todo el búfer en lugar de los bytes que se acaban de leer. -

No estoy seguro de seguir, pero el búfer nunca tendrá más de 30k, y sí, luego envío los 30k completos (o menos) al canal de respuesta. -

Pero podría haberlo hecho menos más de 30K de datos útiles en él. Solo deberías estar escribiendo bytesRead bytes en cada iteración, no los 30K completos. -

Ahh, veo lo que estás diciendo ahora. Buen ojo, trabajaré para arreglar eso. En realidad, estoy un poco sorprendido de que esté funcionando, ya que podría haber basura entre los bytes leídos y el límite de 30k en cada iteración. Supongo que tuve "suerte" y tuve la lectura completa de 30k cada vez en mis pruebas. -

la lectura del disco local normalmente llenará el búfer. Pero su última iteración casi siempre habría sido incorrecta; probablemente tenga muchos archivos que tienen basura final, por así decirlo. En algunos formatos de archivo, eso no importa, por supuesto. -

3 Respuestas

Si está seguro de que solo serán 30K de datos, podría considerar simplificarlo con File.ReadAllBytes.

Respondido 28 ago 11, 05:08

Si aborta la solicitud en el cliente, usando HttpWebRequest.Abort (como en este respuesta) entonces un ThreadAbortException debería aparecer en el servidor en respuesta al final de la conexión TCP, lo que evitará que ese hilo escriba datos.

contestado el 23 de mayo de 17 a las 14:05

Solo entrego el uri al objeto que se lee en la matriz de bytes

Asumiré por el momento que simplemente estás usando el WebClient. La WebClient tiene un CancelAsync método. Los eventargs de OpenReadCompleted tiene un Cancelled propiedad que puede probar.

Cuando el cliente aborta una conexión, el servidor no enviará más bytes, pero el código del servidor continuará ejecutándose, es la parte interna de IIS la que simplemente descartará los búferes que recibe, ya que ya no tiene ningún lugar para enviarlos.

En el servidor puede utilizar el IsClientConnected propiedad de la HttpResponse objeto para determinar si abortar el circuito de la bomba.

Por cierto, deberías considerar mover este código a un .ashx, un .aspx lleva mucho equipaje que no necesitas.

Respondido 28 ago 11, 11:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.