ASP.Net MVC: Cách hiển thị hình ảnh mảng byte từ mô hình


115

Tôi có một mô hình với tệp hình ảnh mảng byte mà tôi muốn hiển thị trên trang.

Làm thế nào tôi có thể làm điều đó mà không cần quay lại Cơ sở dữ liệu?

Tất cả các giải pháp mà tôi thấy đều sử dụng ActionResultđể quay lại cơ sở dữ liệu để truy xuất hình ảnh, nhưng tôi đã có hình ảnh trên mô hình ...


11
Xin vui lòng, ngừng tham khảo "ASP.NET MVC" đơn giản là "MVC". Một là một khung, trong khi khác là một mẫu thiết kế độc lập với ngôn ngữ. Nó giống như gọi IE - "internet"
tereško

MVC Làm thế nào để hiển thị một hình ảnh mảng byte từ mô hình khi null của nó?
Chathz

Câu trả lời:


214

Một cái gì đó như thế này có thể hoạt động ...

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

<img src="@imgSrc" />

Như đã đề cập trong các ý kiến ​​dưới đây, vui lòng sử dụng các kiến ​​thức được trang bị ở trên với mặc dù điều này có thể trả lời câu hỏi của bạn nhưng nó có thể không giải quyết được vấn đề của bạn . Tùy thuộc vào vấn đề của bạn, đây có thể là giải pháp nhưng tôi sẽ không loại trừ hoàn toàn việc truy cập cơ sở dữ liệu hai lần.


6
Cần lưu ý điều này sẽ nhúng hình ảnh vào HTML và sẽ phá vỡ một số kỹ thuật lưu trữ hình ảnh tiêu chuẩn.
Quintin Robinson

@QuintinRobinson Mặc dù giảm số lượng yêu cầu:)
dav_i

8
@dav_i Giảm số lượng yêu cầu ban đầu . Khi tối ưu hóa hiệu suất web, điều cực kỳ quan trọng là phải hiểu các cơ chế của máy chủ, nền tảng nội dung trung gian và các máy khách đang yêu cầu và xử lý thông tin. Tôi không muốn đi sâu vào chi tiết đặc biệt trong một bình luận nhưng tôi muốn nhấn mạnh sự cần thiết phải thực sự hiểu ý nghĩa của việc sử dụng một kỹ thuật như vậy.
Quintin Robinson

1
Câu trả lời có thể đúng cho câu hỏi nhưng tôi nghĩ rằng vấn đề chúng ta đang cố gắng giải quyết có một lỗ hổng. Nếu vấn đề hiện tại là ngăn hai cuộc gọi đến cơ sở dữ liệu để lấy Dữ liệu và sau đó một giây để lấy hình ảnh, tôi nghĩ rằng một giải pháp tốt hơn nhiều là sử dụng một trình xử lý sắp xếp có thể thực hiện lưu trữ để giảm tải tổng thể trên máy chủ. Khi bạn đang cố gắng tìm hiểu lý do tại sao ứng dụng của bạn bị nghẹt thở vì bạn đang cố gắng loại bỏ một tệp khổng lồ bằng cách sử dụng mã hóa Base64 vào luồng phản hồi của trang, bạn sẽ ước mình nghĩ nhiều hơn về bức tranh lớn hơn.
Nick Bork

2
Thật tuyệt, tôi đã thêm một phương thức trên mô hình của mình để sử dụng lại nó: chuỗi công khai GetBase64 () {var base64 = Convert.ToBase64String (ContentImage); trả về String.Format ("data: image / gif; base64, {0}", base64); }
Rodrigo Longo

40

Điều này làm việc cho tôi

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

1
cái này cũng làm việc với tôi, vui lòng nói Làm thế nào để hiển thị hình ảnh mảng byte từ mô hình khi null?
Chathz

Xin chào Chathz, tôi sẽ đề nghị bạn xác thực mô hình trong bộ điều khiển trước khi chuyển đến chế độ xem. Nếu mô hình là null, vượt qua một hình ảnh mặc định
NoloMokgosi

26

Tôi đề xuất một cái gì đó dọc theo những dòng này, ngay cả khi hình ảnh nằm trong mô hình của bạn.

Tôi nhận ra rằng bạn đang yêu cầu một cách trực tiếp để truy cập nó ngay từ chế độ xem và nhiều người khác đã trả lời và nói với bạn điều gì sai với cách tiếp cận đó vì vậy đây chỉ là một cách khác sẽ tải hình ảnh theo kiểu không đồng bộ cho bạn và tôi nghĩ là một cách tiếp cận tốt hơn.

Mô hình mẫu:

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

Phương pháp mẫu trong Bộ điều khiển:

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

    byte[] photoBack = item.InternalImage;

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

Lượt xem

@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
"Tệp trả về (...)" là gì? Không phải là một lớp tĩnh?
Bến cống

3
Nó phải là một đối tượng FileContentResult ( msdn.microsoft.com/en-us/l
Library / 50

13

Một cách là thêm phần này vào lớp c # hoặc lớp HtmlExtensions mới

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 + "' />");
    }
}

sau đó bạn có thể làm điều này trong bất kỳ chế độ xem nào

@Html.Image(Model.ImgBytes)

Tôi thực sự thích điều này nhất - làm cho nó sạch trong Model và cả trong tệp .cshtml. TUYỆT QUÁ!!
Ken

10

Nếu bạn có thể mã hóa cơ sở 64, bạn có thể thử sử dụng kết quả làm nguồn hình ảnh của mình. Trong mô hình của bạn, bạn có thể thêm một cái gì đó như:

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);
    }
}

Và theo quan điểm của bạn:

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

5

Nếu hình ảnh không lớn và nếu có cơ hội tốt, bạn sẽ thường xuyên sử dụng lại hình ảnh và nếu bạn không có quá nhiều hình ảnh và nếu hình ảnh không bí mật (có nghĩa là nó không lớn thỏa thuận nếu một người dùng có khả năng nhìn thấy hình ảnh của người khác) ...

Rất nhiều "nếu" ở đây, vì vậy rất có thể đây là một ý tưởng tồi:

Bạn có thể lưu trữ các byte hình ảnh trong Cachemột thời gian ngắn và tạo một thẻ hình ảnh hướng về một phương thức hành động, lần lượt đọc từ bộ đệm và phun ra hình ảnh của bạn. Điều này sẽ cho phép trình duyệt lưu trữ hình ảnh một cách thích hợp.

// 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");
}

Điều này có thêm lợi ích (hoặc là một cái nạng?) Khi làm việc trong các trình duyệt cũ hơn, trong đó các hình ảnh nội tuyến không hoạt động trong IE7 (hoặc IE8 nếu lớn hơn 32kB).


3

Đây là phiên bản sửa đổi của câu trả lời của Manoj mà tôi sử dụng cho một dự án. Chỉ cần cập nhật để nhận một lớp, thuộc tính html và sử dụng 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));
    }

Mà có thể được sử dụng sau đó như sau:

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

3

Bạn cần phải có một byte [] trong DB của mình.

Byte của tôi [] nằm trong đối tượng Person của tôi:

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


Bạn cần chuyển đổi byte [] trong Chuỗi. Vì vậy, tôi có trong bộ điều khiển của mình:

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


Tiếp theo, trong tệp .cshtml của tôi, Model của tôi là ViewModel. Đây là những gì tôi có trong:

 public String Image { get; set; }


Tôi sử dụng nó như thế này trong tệp .cshtml của tôi:

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

"data: phần mở rộng tập tin hình ảnh / hình ảnh ; base64, {0}, Chuỗi hình ảnh của bạn "

Tôi ước nó sẽ giúp được ai đó!


1

Nếu bạn muốn trình bày hình ảnh, hãy thêm một phương thức như một lớp trợ giúp hoặc vào chính mô hình đó và cho phép phương thức chuyển đổi hình ảnh mảng byte thành định dạng hình ảnh như PNG hoặc JPG sau đó chuyển đổi thành chuỗi Base64. Khi bạn đã có điều đó, liên kết giá trị base64 trên chế độ xem của bạn ở định dạng

"data: image / [phần mở rộng loại tệp hình ảnh] ; base64, [chuỗi base64 của bạn ở đây] "

Ở trên được gán cho thuộc tính imgcủa thẻ src.

Vấn đề duy nhất tôi có với điều này là chuỗi base64 quá dài. Vì vậy, tôi sẽ không đề xuất nó cho nhiều mô hình được hiển thị trong một khung nhìn.


Bạn đưa ra một vấn đề và nêu một kịch bản ca sử dụng không khuyến nghị, nhưng không có giải pháp nào cho kịch bản ca sử dụng của bạn. Điều đó sẽ làm cho câu trả lời của bạn đẹp hơn / hữu ích và nhiều thông tin hơn.
Ken

0

Tôi đã tạo ra một phương thức trợ giúp dựa trên asnwer bên dưới và tôi rất vui vì người trợ giúp này có thể giúp đỡ nhiều nhất có thể.

Với một mô hình:

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

Người trợ giúp là:

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));
    }

Chế độ xem đang nhận được một đối tượng: ICollection, do đó bạn cần sử dụng nó trong chế độ xem trong một tuyên bố foreach:

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.