Отображение изображения базы данных (байт []) в Razor / MVC3? - PullRequest
22 голосов
/ 12 декабря 2011

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

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

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

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

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

@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 -

В моем продолжающемся поиске эффективности (без необходимости делать еще один запрос к БД) помощник 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>
}

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

Ответы [ 7 ]

20 голосов
/ 08 июня 2013

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" />
9 голосов
/ 15 декабря 2011

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

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

    [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" });
5 голосов
/ 12 декабря 2011

Я не думаю, что наличие байтового массива в вашем View поможет вам. Вам нужно использовать действие контроллера в качестве 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"/>
3 голосов
/ 17 января 2014

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

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

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

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

2 голосов
/ 12 декабря 2011

Вы можете просто сделать Response.Write (ваш байтовый массив) и установить для Response.ContentType значение image / 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" />

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

Возможно, это не совсем ответ на ваш вопрос, но это сработает.

0 голосов
/ 13 декабря 2011

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

0 голосов
/ 12 декабря 2011

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

Еще больше информации о проблеме можно найти здесь Больше подробностей о проблеме .

В конце концов, ради того, чтобы не иметь взлома из-за того, что я считаю, вероятно, ошибкой в ​​IE9, я остановился на чтении 'two', но не должноне нужно.

...