Konwertuj HttpPostedFileBase na bajt []

123

W mojej aplikacji MVC używam następującego kodu, aby przesłać plik.

MODEL

 public HttpPostedFileBase File { get; set; }

WIDOK

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

Wszystko działa dobrze .. Ale próbuję przekonwertować wynikowy fiel na bajt [] .Jak mogę to zrobić

KONTROLER

 public ActionResult ManagePhotos(ManagePhotos model)
    {
        if (ModelState.IsValid)
        {
            byte[] image = model.File; //Its not working .How can convert this to byte array
        }
     }
Wskaźnik zerowy
źródło

Odpowiedzi:

259

Jak mówi Darin, możesz czytać ze strumienia wejściowego - ale unikałbym polegania na wszystkich danych dostępnych za jednym razem. Jeśli używasz .NET 4, jest to proste:

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

CopyToJeśli chcesz, możesz łatwo napisać odpowiednik w .NET 3.5. Ważną częścią jest to, że czytaszHttpPostedFileBase.InputStream .

W celu efektywnego Państwo mogli sprawdzić, czy strumień wrócił już jest 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
źródło
Pierwszy przykład nie działał dla mnie w .NET4 (nie wypróbowałem drugiego) - Nie działał, gdy próbowałem go z .png lub .jpg, jednak działał, gdy korzystałem z pliku .txt . Każdy pomysł dlaczego :)
VoodooChild
2
@VoodooChild: Prawdopodobnie coś w tym, co robisz, traktuje dane jako tekst. Musiałbym zobaczyć więcej kodu, żeby wiedzieć co. Proponuję zadać kolejne pytanie, podając pełny scenariusz.
Jon Skeet
6
ok, to zadziałało, żeby nadać kontekst - dzięki! `Image img = Image.FromStream (file.InputStream); MemoryStream ms = new MemoryStream (); img.Save (ms, ImageFormat.Jpeg); model.SiteLogo = ms.ToArray (); `
VoodooChild
7
Odkryłem, że pozycja strumienia wejściowego znajdowała się na końcu strumienia, więc musiałem dodać wiersz model.File.InputStream.Position = 0;przed kodem Jona, aby działał
Manish
2
@UweKeim: Cóż, tak, mamy już instrukcję using (nie dyrektywę, btw) dla inputStreami obie będą odnosić się do tego samego obiektu. Dlaczego miałbyś chcieć go pozbyć się dwa razy?
Jon Skeet
27

Możesz to przeczytać ze strumienia wejściowego:

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
    }
    ...
}

A jeśli zamierzasz bezpośrednio zapisać plik na dysku, możesz użyć tej model.File.SaveAsmetody. Poniższy wpis na blogu może okazać się przydatny.

Darin Dimitrov
źródło
5
Czy InputStream dla HttpPostedFileBase gwarantuje, że zwróci wszystkie dane w jednym wywołaniu Read? Jeśli to możliwe, najlepiej tego unikać.
Jon Skeet