Convertir HttpPostedFileBase a byte []

123

En mi aplicación MVC, estoy usando el siguiente código para cargar un archivo.

MODELO

 public HttpPostedFileBase File { get; set; }

VER

@Html.TextBoxFor(m => m.File, new { type = "file" })

Todo funciona bien ... Pero estoy tratando de convertir el campo de resultado en byte []. ¿Cómo puedo hacer esto?

CONTROLADOR

 public ActionResult ManagePhotos(ManagePhotos model)
    {
        if (ModelState.IsValid)
        {
            byte[] image = model.File; //Its not working .How can convert this to byte array
        }
     }
Puntero nulo
fuente

Respuestas:

259

Como dice Darin, puede leer desde la secuencia de entrada, pero evitaría confiar en que todos los datos estén disponibles de una sola vez. Si está utilizando .NET 4, esto es simple:

MemoryStream target = new MemoryStream();
model.File.InputStream.CopyTo(target);
byte[] data = target.ToArray();

Es bastante fácil escribir el equivalente de CopyTo.NET 3.5 si lo desea. La parte importante es que lees HttpPostedFileBase.InputStream.

Para fines eficientes, puede verificar si la secuencia devuelta ya es un MemoryStream:

byte[] data;
using (Stream inputStream = model.File.InputStream)
{
    MemoryStream memoryStream = inputStream as MemoryStream;
    if (memoryStream == null)
    {
        memoryStream = new MemoryStream();
        inputStream.CopyTo(memoryStream);
    }
    data = memoryStream.ToArray();
}
Jon Skeet
fuente
El primer ejemplo no funcionó para mí en .NET4 (no probé el otro): no funcionó cuando lo probé con un .png o .jpg, sin embargo, funcionó cuando utilicé un archivo .txt . Alguna idea de por qué :)
VoodooChild
2
@VoodooChild: Presumiblemente, algo en lo que estás haciendo es tratar los datos como texto. Sin embargo, necesitaría ver más código para saber qué. Le sugiero que haga otra pregunta dando su escenario completo.
Jon Skeet
66
ok esto funcionó para mí, solo para dar un poco de contexto - ¡Gracias! `Image img = Image.FromStream (archivo.InputStream); MemoryStream ms = nuevo MemoryStream (); img.Save (ms, ImageFormat.Jpeg); model.SiteLogo = ms.ToArray (); `
VoodooChild
77
Estaba descubriendo que la posición del flujo de entrada estaba al final del flujo, así que tuve que agregar la línea model.File.InputStream.Position = 0;antes del código de Jon para que funcionara
Manish
2
@UweKeim: Bueno, sí, ya tenemos una declaración de uso (no directiva, por cierto) para inputStream, y ambos se referirán al mismo objeto. ¿Por qué querrías deshacerte de él dos veces?
Jon Skeet
27

Puedes leerlo desde la secuencia de entrada:

public ActionResult ManagePhotos(ManagePhotos model)
{
    if (ModelState.IsValid)
    {
        byte[] image = new byte[model.File.ContentLength];
        model.File.InputStream.Read(image, 0, image.Length); 

        // TODO: Do something with the byte array here
    }
    ...
}

Y si tiene la intención de guardar directamente el archivo en el disco, puede usar el model.File.SaveAsmétodo. Puede encontrar útil la siguiente publicación de blog .

Darin Dimitrov
fuente
55
¿Se garantiza que InputStream para un HttpPostedFileBase devuelva todos sus datos en una sola llamada a Read? Es mejor evitar eso cuando sea posible.
Jon Skeet