ASP.Net MVC : 모델에서 바이트 배열 이미지를 표시하는 방법


115

페이지에 표시하려는 바이트 배열 이미지 파일이있는 모델이 있습니다.

데이터베이스로 돌아 가지 않고 어떻게 할 수 있습니까?

내가 보는 모든 솔루션은를 사용 ActionResult하여 데이터베이스로 돌아가 이미지를 검색하지만 이미 모델에 이미지가 있습니다.


11
"ASP.NET MVC"를 단순히 "MVC"라고 부르지 마십시오. 하나는 프레임 워크이고 다른 하나는 언어 독립적 인 디자인 패턴입니다. "인터넷"- 그것은 IE를 호출처럼
tereško

MVC null 일 때 모델에서 바이트 배열 이미지를 표시하는 방법은 무엇입니까?
Chathz

답변:


214

이런 식으로 작동 할 수 있습니다 ...

@{
    var base64 = Convert.ToBase64String(Model.ByteArray);
    var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
}

<img src="@imgSrc" />

아래 의견에서 언급했듯이 위의 내용은 귀하의 질문에 답할 수 있지만 문제가 해결되지 않을 수 있다는 사실을 알고 사용하십시오 . 문제에 따라 이것이 해결책이 될 수 있지만 데이터베이스에 두 번 액세스하는 것을 완전히 배제하지는 않습니다.


6
이렇게하면 HTML에 이미지가 포함되고 몇 가지 표준 이미지 캐싱 기술을 피할 수 있습니다.
Quintin Robinson

@QuintinRobinson 비록 요청의 수 감소:)
dav_i

8
@dav_i 초기 요청 수를 줄 입니다. 웹 성능을 최적화 할 때 정보를 요청하고 처리하는 서버, 중간 콘텐츠 플랫폼 및 클라이언트의 메커니즘을 이해하는 것은 매우 중요합니다. 나는 코멘트에서 특별한 세부 사항을 다루고 싶지 않지만 그러한 기술 사용의 의미를 진정으로 이해해야 할 필요성을 강조하고 싶습니다.
Quintin Robinson

1
질문에 대한 답은 정확할 수 있지만 해결하려는 문제에 결함이 있다고 생각합니다. 당면한 문제가 데이터를 얻기 위해 데이터베이스에 대한 두 번의 호출을 방해하고 이미지를 얻기위한 두 번째 호출을 방해하는 경우 훨씬 더 나은 해결책은 캐싱을 구현할 수있는 처리기를 사용하여 서버의 전체 부하를 줄이는 것입니다. 페이지 응답 스트림에 Base64 인코딩을 사용하여 거대한 파일을 덤프하려고하기 때문에 애플리케이션이 왜 질식하는지 알아 내려고 할 때 더 큰 그림에 대해 더 많이 생각했으면 좋을 것입니다.
Nick Bork

2
좋습니다. 다시 사용하기 위해 모델에 메서드를 추가했습니다. public string GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); return String.Format ( "data : image / gif; base64, {0}", base64); }
Rodrigo Longo 2016

40

이것은 나를 위해 일했습니다.

<img src="data:image;base64,@System.Convert.ToBase64String(Model.CategoryPicture.Content)" width="80" height="80"/>     

1
이 하나도 나를 위해 일했다, 친절하게 말하면 모델에서 바이트 배열 이미지를 표시하는 방법은 null?
Chathz

안녕하세요 Chathz, 뷰로 전달하기 전에 컨트롤러에서 모델을 검증하는 것이 좋습니다. 모델이 null 인 경우 기본 사진 전달
NoloMokgosi

26

이미지가 모델 내부에 있더라도이 선을 따라 무언가를 권장합니다.

나는 당신이보기에서 바로 접근 할 수있는 직접적인 방법을 요구하고 있다는 것을 알고 있으며 많은 다른 사람들이 그 접근 방식에 무엇이 잘못되었는지에 대해 대답했고 이것은 당신과 저를 위해 비동기 방식으로 이미지를로드하는 또 다른 방법 일뿐입니다. 더 나은 접근 방식이라고 생각하십시오.

샘플 모델 :

[Bind(Exclude = "ID")]
public class Item
{
    [Key]
    [ScaffoldColumn(false)]
    public int ID { get; set; }

    public String Name { get; set; }

    public byte[] InternalImage { get; set; } //Stored as byte array in the database.
}

컨트롤러의 샘플 방법 :

public async Task<ActionResult> RenderImage(int id)
{
    Item item = await db.Items.FindAsync(id);

    byte[] photoBack = item.InternalImage;

    return File(photoBack, "image/png");
}

전망

@model YourNameSpace.Models.Item

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
<h4>Item</h4>
<hr />
<dl class="dl-horizontal">
    <img src="@Url.Action("RenderImage", new { id = Model.ID})" />
</dl>
<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Name)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Name)
    </dd>
</dl>
</div>

2
"return File (...)"이란 무엇입니까? File은 정적 클래스가 아닌가요?
Ben Sewards

3
그것은 (A FileContentResult 오브젝트해야 msdn.microsoft.com/en-us/library/... )
루이 Bacaj

13

한 가지 방법은이를 새 C # 클래스 또는 HtmlExtensions 클래스에 추가하는 것입니다.

public static class HtmlExtensions
{
    public static MvcHtmlString Image(this HtmlHelper html, byte[] image)
    {
        var img = String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(image));
        return new MvcHtmlString("<img src='" + img + "' />");
    }
}

그런 다음 모든보기에서이 작업을 수행 할 수 있습니다.

@Html.Image(Model.ImgBytes)

저는 이것이 가장 마음에 듭니다. Model과 .cshtml 파일에서도 깔끔하게 만듭니다. 큰!!
Ken

10

바이트를 base-64로 인코딩 할 수있는 경우 결과를 이미지 소스로 사용해 볼 수 있습니다. 모델에 다음과 같이 추가 할 수 있습니다.

public string ImageSource
{
    get
    {
        string mimeType = /* Get mime type somehow (e.g. "image/png") */;
        string base64 = Convert.ToBase64String(yourImageBytes);
        return string.Format("data:{0};base64,{1}", mimeType, base64);
    }
}

그리고 당신의 관점에서 :

<img ... src="@Model.ImageSource" />

5

이미지가 그렇게 크지 않고 좋은 기회가 있다면 이미지를 자주 재사용하게 될 것이고, 이미지가 너무 많지 않은 경우, 이미지가 비밀이 아닌 경우 (크지 않다는 의미) 한 사용자가 잠재적으로 다른 사람의 이미지를 볼 수있는 경우 거래) ...

여기에 많은 "if"가 있으므로 이것이 나쁜 생각 일 가능성이 높습니다.

Cache짧은 시간 동안 이미지 바이트를 저장하고 이미지 태그를 작업 메서드를 가리 키도록 만들 수 있습니다. 그러면 캐시에서 읽어서 이미지를 뱉어냅니다. 이렇게하면 브라우저가 이미지를 적절하게 캐시 할 수 있습니다.

// In your original controller action
HttpContext.Cache.Add("image-" + model.Id, model.ImageBytes, null,
    Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1),
    CacheItemPriority.Normal, null);

// In your view:
<img src="@Url.Action("GetImage", "MyControllerName", new{fooId = Model.Id})">

// In your controller:
[OutputCache(VaryByParam = "fooId", Duration = 60)]
public ActionResult GetImage(int fooId) {
    // Make sure you check for null as appropriate, re-pull from DB, etc.
    return File((byte[])HttpContext.Cache["image-" + fooId], "image/gif");
}

이것은 인라인 이미지가 IE7 (또는 32kB보다 큰 경우 IE8)에서 작동하지 않는 구형 브라우저에서 작동하는 추가 이점 (또는 신조인가?)이 있습니다.


3

이것은 내가 프로젝트에서 사용하는 Manoj의 대답의 수정 된 버전입니다. 클래스, html 속성을 취하고 TagBuilder를 사용하도록 업데이트되었습니다.

    public static IHtmlString Image(this HtmlHelper helper, byte[] image, string imgclass, 
                                     object htmlAttributes = null)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("class", imgclass);
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        var imageString = image != null ? Convert.ToBase64String(image) : "";
        var img = string.Format("data:image/jpg;base64,{0}", imageString);
        builder.MergeAttribute("src", img);

        return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
    }

다음과 같이 사용할 수 있습니다.

    @Html.Image(Model.Image, "img-cls", new { width="200", height="200" })

3

DB에 byte []가 있어야합니다.

내 byte []는 내 Person 객체에 있습니다.

public class Person
{
    public byte[] Image { get; set; }
}


byte []를 문자열로 변환해야합니다. 그래서 내 컨트롤러에 있습니다.

String img = Convert.ToBase64String(person.Image);


다음으로 내 .cshtml 파일에서 내 모델은 ViewModel입니다. 이것이 내가 가진 것입니다.

 public String Image { get; set; }


내 .cshtml 파일에서 다음과 같이 사용합니다.

<img src="@String.Format("data:image/jpg;base64,{0}", Model.Image)" />

"data : image / image file extension ; base64, {0}, your image String "

누군가를 도울 것입니다!


1

이미지를 표시하려면 메서드를 도우미 클래스로 추가하거나 모델 자체에 추가하고 메서드가 바이트 배열 이미지를 PNG 또는 JPG와 같은 이미지 형식으로 변환 한 다음 Base64 문자열로 변환하도록 허용합니다. 그런 다음 뷰의 base64 값을 형식으로 바인딩하십시오.

"data : image / [이미지 파일 유형 확장자] ; base64, [여기에 base64 문자열 입력] "

위는 img태그의 src속성에 할당됩니다 .

내가 가진 유일한 문제는 base64 문자열이 너무 길다는 것입니다. 따라서보기에 여러 모델이 표시되는 경우에는 권장하지 않습니다.


문제를 제기하고 권장하지 않는 사용 사례 시나리오를 명시하지만 사용 사례 시나리오에 대한 해결책은 없습니다. 그것은 당신의 대답을 훨씬 더 좋고 유용하고 유익하게 만들었을 것입니다.
Ken

0

아래 asnwer를 기반으로 도우미 메서드를 만들었으며이 도우미가 가능한 한 많은 도움을 줄 수있어 매우 기쁩니다.

모델 사용 :

 public class Images
 {
    [Key]
    public int ImagesId { get; set; }
    [DisplayName("Image")]
    public Byte[] Pic1 { get; set; }
  }

도우미는 다음과 같습니다.

public static IHtmlString GetBytes<TModel, TValue>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TValue>> expression, byte[] array, string Id)
    {
        TagBuilder tb = new TagBuilder("img");
        tb.MergeAttribute("id", Id);
        var base64 = Convert.ToBase64String(array);
        var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
        tb.MergeAttribute("src", imgSrc);
        return MvcHtmlString.Create(tb.ToString(TagRenderMode.SelfClosing));
    }

뷰는 ICollection 개체를 수신하므로 foreach 문의 뷰에서 사용해야합니다.

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.