Devolviendo una secuencia desde un archivo.OpenRead()


Estoy en el proceso de escribir un servicio WCF que permitirá un ASP.Net sitio web para recuperar archivos (basado en este artículo ). Mi problema es que cuando devuelvo la transmisión, está en blanco.

Para simplificar, he aislado el código en una simple aplicación winforms para tratar de encontrar cuál es el problema con devolver una secuencia y este es el código:

    private Stream TestStream()
    {
        Stream fs = File.OpenRead(@"c:\testdocument.docx");
        return fs;
    }

    // This method converts the filestream into a byte array so that when it is 
    // used in my ASP.Net project the file can be sent using response.Write
    private void Test()
    {            
        System.IO.MemoryStream data = new System.IO.MemoryStream();
        System.IO.Stream str = TestStream();

        str.CopyTo(data);
        byte[] buf = new byte[data.Length];
        data.Read(buf, 0, buf.Length);                       
    }

El resultado de este código es que buf tiene 12.587 bytes de largo (la longitud correcta del archivo) pero solo contiene 0's.

El documento de Word se abre sin problemas si lo intento, ¿me estoy perdiendo algo obvio?

Author: GrandMasterFlush, 2012-01-05

5 answers

Olvidaste buscar:

str.CopyTo(data);
data.Seek(0, SeekOrigin.Begin); // <-- missing line
byte[] buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
 34
Author: ken2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-08 13:42:35

Opciones:

  • Use data.Seek como sugiere ken2k
  • Use la propiedad algo más simple Position:

    data.Position = 0;
    
  • Use la llamada ToArray en MemoryStream para hacer su vida más simple para comenzar con:

    byte[] buf = data.ToArray();
    

La tercera opción sería mi enfoque preferido.

Tenga en cuenta que debe tener una instrucción using para cerrar el flujo de archivos automáticamente (y opcionalmente para MemoryStream), y agregaría una directiva de uso para System.IO para hacer su código limpiador:

byte[] buf;
using (MemoryStream data = new MemoryStream())
{
    using (Stream file = TestStream())
    {
        file.CopyTo(data);
        buf = data.ToArray();
    }
}

// Use buf

Es posible que también desee crear un método de extensión en Stream para hacer esto por usted en un solo lugar, por ejemplo,

public static byte[] CopyToArray(this Stream input)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        input.CopyTo(memoryStream);
        return memoryStream.ToArray();
    }
}

Tenga en cuenta que este no cierra el flujo de entrada.

 12
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 11:19:43

Olvidó restablecer la posición del flujo de memoria:

private void Test()
{            
    System.IO.MemoryStream data = new System.IO.MemoryStream();
    System.IO.Stream str = TestStream();

    str.CopyTo(data);
    // Reset memory stream
    data.Seek(0, SeekOrigin.Begin);
    byte[] buf = new byte[data.Length];
    data.Read(buf, 0, buf.Length);                       
}

Actualización:

Hay una cosa más a tener en cuenta: Por lo general vale la pena no ignorar los valores devueltos de los métodos. Una implementación más robusta debería comprobar cuántos bytes se han leído después de que la llamada regrese:

private void Test()
{            
    using(MemoryStream data = new MemoryStream())
    {
        using(Stream str = TestStream())
        {
           str.CopyTo(data);
        }
        // Reset memory stream
        data.Seek(0, SeekOrigin.Begin);
        byte[] buf = new byte[data.Length];
        int bytesRead = data.Read(buf, 0, buf.Length);

        Debug.Assert(bytesRead == data.Length, 
                    String.Format("Expected to read {0} bytes, but read {1}.",
                        data.Length, bytesRead));
    }                     
}
 5
Author: afrischke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-08 02:32:16

Necesitas

    str.CopyTo(data);
    data.Position = 0; // reset to beginning
    byte[] buf = new byte[data.Length];
    data.Read(buf, 0, buf.Length);  

Y dado que su método Test() está imitando al cliente, debería Close() o Dispose() el flujo str. Y el sueño de memoria también, fuera de lo principal.

 3
Author: Henk Holterman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 11:24:05

Intenta cambiar tu código a esto:

private void Test()
{            
    System.IO.MemoryStream data = new System.IO.MemoryStream(TestStream());

    byte[] buf = new byte[data.Length];
    data.Read(buf, 0, buf.Length);                       
}
 1
Author: ilivewithian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 11:17:47