Преобразовать HttpPostedFileBase в byte []

123

В моем приложении MVC я использую следующий код для загрузки файла.

МОДЕЛЬ

 public HttpPostedFileBase File { get; set; }

ПОСМОТРЕТЬ

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

Все работает нормально .. Но я пытаюсь преобразовать результат в byte []. Как я могу это сделать

КОНТРОЛЛЕР

 public ActionResult ManagePhotos(ManagePhotos model)
    {
        if (ModelState.IsValid)
        {
            byte[] image = model.File; //Its not working .How can convert this to byte array
        }
     }
Нулевой указатель
источник

Ответы:

259

Как говорит Дарин, вы можете читать из входного потока, но я бы не стал полагаться на то, что все данные будут доступны за один раз. Если вы используете .NET 4, это просто:

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

CopyToЕсли хотите, достаточно просто написать эквивалент .NET 3.5. Важная часть - это то, что вы читаете HttpPostedFileBase.InputStream.

Для повышения эффективности вы можете проверить, является ли уже возвращенный поток 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();
}
Джон Скит
источник
Первый пример не работал у меня в .NET4 (другой не пробовал) - он не работал, когда я пробовал его с .png или .jpg, однако он работал, когда я использовал файл .txt , Любая идея, почему :)
VoodooChild
2
@VoodooChild: Предположительно, что-то в том, что вы делаете, обрабатывает данные как текст. Мне нужно увидеть больше кода, чтобы знать, что именно. Предлагаю вам задать еще один вопрос и изложить свой полный сценарий.
Джон Скит
6
хорошо, это сработало для меня, просто чтобы дать некоторый контекст - Спасибо! `Изображение img = Image.FromStream (file.InputStream); MemoryStream ms = новый MemoryStream (); img.Save (мс, ImageFormat.Jpeg); model.SiteLogo = ms.ToArray (); `
VoodooChild
7
Я обнаружил, что позиция входного потока находится в конце потока, поэтому мне пришлось добавить строку model.File.InputStream.Position = 0;перед кодом Джона, чтобы заставить его работать
Маниш
2
@UweKeim: Ну да, у нас уже есть оператор using (не директива, кстати) для inputStream, и оба будут ссылаться на один и тот же объект. Зачем вам нужно утилизировать его дважды?
Джон Скит,
27

Вы можете прочитать его из входного потока:

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

И если вы намереваетесь напрямую сохранить файл на диск, вы можете использовать этот model.File.SaveAsметод. Возможно, вам будет полезно следующее сообщение в блоге .

Дарин Димитров
источник
5
Гарантируется ли, что InputStream для HttpPostedFileBase вернет все свои данные за один вызов Read? По возможности лучше этого избегать.
Джон Скит