Подтвердить что ты не робот

Отображение изображения базы данных (байты []) в Razor/MVC3?

Я возвращаю набор данных из моей базы данных MS SQL 2008R2, которая содержит данные, которые я уже получаю от данных в режиме Razor. Я добавил поле byte [], которое содержит эскиз изображения, который я пытаюсь отобразить в этом представлении.

Поскольку массив байтов относительно крошечный, я решил, что попробую отобразить массив байтов inline. Однако после прочтения могут возникнуть некоторые проблемы, связанные с браузером, я отказался от этого.

Создание метода контроллера казалось возможным (оба метода найдены здесь), однако у меня уже есть массив байтов, готовый пойти на мой взгляд, и дон Вам нужно сделать другой вызов db, чтобы получить его на основе идентификатора.

Выполнение этого, не работает по понятным причинам:

... отображение других данных на странице....

@if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] == null)
{
    <img src="@Url.Content("~/Content/Images/NoPhoto.png")" border="0" />
}
else
{
    <img src="@Url.Action("GetImage", "SearchResults", new { imageBytes = Model.dsResults.Tables[0].Rows[i]["ImageBytes"] })" alt="Product Image" />
}

...

Метод контроллера:

[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetImage(byte[] imageBytes)
{
    byte[] byteArray = imageBytes;
    return new FileContentResult(byteArray, "image/jpeg");
}

... поскольку это по существу пытается отправить массив байтов через http.

Итак, на мой вопрос, так как у меня уже есть массив байтов на моем представлении Razor, как его отобразить?

- Обновление -

Я понимаю, что делать обработку в представлении не рекомендуется, но поскольку данные уже существуют, не может быть сделано подобное:

Response.Write((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]);

Или...

Stream s = new MemoryStream(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
System.Drawing.Image img = new System.Drawing.Bitmap(s);

В других сообщениях я прочитал, что вы делаете Response.Write(byte []...)), но в этом случае это не работает.

- UPADATE -

В моем постоянном поиске эффективности (не нужно делать другой запрос в db) WebImage помощник кажется хорошим кандидат. Один из его конструкторов примет байтовый массив для инициализации класса, а затем используя метод .Write( "jpeg" ), я вижу изображение.

<td>
    @{
        WebImage webImage = new WebImage(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
        webImage.Write("jpeg");
    }
</td>

Проблема с использованием WebImage.Write() заключается в том, что после использования изображение является единственным, что отображается на странице. Есть ли способ сделать это прямо на "контроле" на странице просмотра Razor?

- ОБНОВЛЕНИЕ -

Это продолжает меня беспокоить... поэтому я попробовал следующее, которое, как я полагал, может работать, поскольку это то, что мы делаем из Action...

if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] != DBNull.Value)
{
    var img1 = new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg");
    <text>
        <img src="@new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg")" />
    </text>
}

... не работает.

4b9b3361

Ответ 1

В конце концов, я отправился на два маршрута поездки. Очень неэффективно, так как байты изображения уже готовы к просмотру. Должен быть элемент управления веб-помощником, который будет отображать изображение непосредственно из массива байтов изображения (или типа изображения). Может быть, есть, и я пропустил это.

Чтобы получить байты (да, сначала):

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult GetThumbnailImage(string itemListID)
    {
        byte[] imageBytes = null;

        client = new FeederServiceClient();
        imageBytes = client.GetItemThumbnail( itemListID );

        if (imageBytes == null)
        {
            return new FilePathResult("~/Content/Images/NoPhoto.png", "image/png");
        }
        else
        {
            return new FileContentResult(imageBytes, "image/jpeg");
        }
    }

Затем для отображения изображения:

<img src="@Url.Content("~/Thumbnails/" + @Model.dsResults.Tables[0].Rows[i]["ItemListID"] )" />

Следующим маршрутом, помещенным в Global.asax:

routes.MapRoute(name: "Thumbnails", url: "Thumbnails/{itemListID}", defaults: new { controller = "Results", action = "GetThumbnailImage" });

Ответ 2

Model.Content - это байт [].

@{
    string imageBase64 = Convert.ToBase64String(Model.Content);
    string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
}

Используется так:

<img src="@imageSrc" alt="@Model.Name" width="100" height="100" />

Ответ 3

Я не думаю, что использование байтового массива в вашем представлении поможет вам. Вам нужно будет использовать действие контроллера как img src, как описано в связанном ответе.

[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Image(int id)
{
    byte[] byteArray = _imageRepository.GetImage(id);
    return new FileContentResult(byteArray, "image/jpeg");
}


<img src="Image/1234" alt="Image 1234"/>

Ответ 4

Следующее будет работать:

<img src="data:image/jpg;base64,@(Convert.ToBase64String(item.PhotoImage))" alt="@item.orientation" />

в моем приложении, я определил модель на странице RAZOR как элемент, а не модель. PhotoImage - это мой байтовый массив (фактически поле изображения в SQL), а Orientation - это только строковый столбец, который сообщает метаданные о фотографии.

Я долго искал, прежде чем нашел этот ответ, и это сработало для меня. Надеюсь, что это поможет.

Ответ 5

Вы можете просто выполнить Response.Write(ваш массив байтов) и установить Response.ContentType для изображения /jpeg в вашем действии Controller. Это отобразит его непосредственно как изображение.

UPDATE

Код может выглядеть примерно так:

    [Authorize]
    [AcceptVerbs(HttpVerbs.Get)]
    public void GetImage(int id)
    {
        byte[] imageArray = GetImageBytesFromDb(id); // some method for returning the byte-array from db.
        Response.ContentType = "image/png";
        Response.Write(imageArray);       
    }

Теперь вы можете сделать следующее в своем представлении:

 <img src="@Url.Action("GetImage", "SearchResults", new { id= Model.dsResults.Tables[0].Rows[i]["Id (or whatever the id of the row is)"] })" alt="Product Image" />

Итак, другими словами, вместо использования байтов непосредственно в представлении вы вызываете действие контроллера, которое возвращает байты из строки базы данных на основе идентификатора строки (или продукта, если это объект строка)

Это может быть не совсем ответ на ваш вопрос, но он будет работать.

Ответ 6

Это один из способов избежать второй ненужной поездки в базу данных. memystream to Image, но он поставляется с собственной проблемой при использовании в IE9 (все остальные браузеры и версии IE работают нормально).

Более подробную информацию о проблеме можно найти здесь Подробнее о проблемах.

В конце концов, ради того, чтобы не взломать то, что я думаю, вероятно, ошибка в IE9, я пошел с "двумя" чтениями, но не должно быть необходимости.

Ответ 7

Если вы не против использования сеанса, вы можете поместить свою модель в Session (ересь!), а затем визуализировать свое представление как обычно, но теперь, когда вы хотите, чтобы изображения отображались, вы вызываете действие контроллера с помощью Url.Action Идентификатор изображения, который вы хотите. Затем вытащите модель из сеанса, найдите изображение в своей модели для этого идентификатора, сделайте FiLeContentResult (массив, imgtype) в вашем массиве байтов и альт-изображениях прямо из вашей модели на вашу страницу. Не нужно снова обращаться к реальной базе данных, но если вы используете Session SQL State, то obv. вы попадете в базу данных намного хуже, чем раньше, но если вы InProc.... ну, это один из способов сделать это. Я не уверен, что у IE9 все еще есть небольшая проблема с кешированием, но вы всегда можете передать уникальный идентификатор вместе с вашим реальным идентификатором, чтобы убедиться, что этого не произойдет. Это потрепанное решение, но оно работает.