【问题标题】:How to display an image saved on database in .NET Core API?如何在 .NET Core API 中显示保存在数据库中的图像?
【发布时间】:2021-07-14 05:54:37
【问题描述】:

我想显示保存到数据库中的图像,我一直在寻找教程等等,但它们并没有太大帮助。我有一个 API 控制器,它由 MVC 视图及其各自的控制器使用。在视图中有一个显示文本的空间和图像应该放置的空间,图像在数据库中保存为varbinary类型,文本是varchar类型的字段。

我创建的模型:

public class ForumContentModel
{
    //some other fields
    //theme tables
    public string Content { get; set; }
    public byte[] ContentFile { get; set; } //this has the image
    public string FileType { get; set; }//the ext type of the image
    public string FileName { get; set; }//the name of the img

}

API 控制器:

    [HttpGet]
    [Route("watchPost/{IdPost}")]
    public IActionResult verPost(int IdPost)
    {
        ForumContentModel forum = new ForumContentModel();//this model is used to "join" various
                                                          //models

        //get the data from the different tables with the id sending from the MVC controller
        var forumContent = db.Themes.Where(x => x.IdForo == IdPost).FirstOrDefault();            

        //Content data from the post

        forum.Content = forumContent.Content;//the text part

        forum.ContentFile = forumContent.ContentFile;//the image
        return Ok(forum);
     }

MVC 控制器:

    [HttpGet]
    public IActionResult watchPost(int Id)
    {
        ForumContentModel forumModel = new ForumContentModel();

        using(var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://localhost:44325/api/Forum/");

            var responseTask = client.GetAsync("watchPost/" + Id);

            responseTask.Wait();

            var result = responseTask.Result;

            if(result.IsSuccessStatusCode)
            {
                var readTask = result.Content.ReadAsAsync<ForumContentModel>();
                readTask.Wait();

                forumModel = readTask.Result;
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Server error");
            }
        }

        return View(forumModel);
    }

显示数据的视图:

       <form asp-action="watchPost">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="row">
                <div class="form-group col-8">
                    <!--Text content-->
                    <label asp-for="Content" class="control-label h2"></label>
                    <textarea rows="4" asp-for="Content" class="form-control border-0" readonly="readonly"></textarea>
                    <span asp-validation-for="Content" class="text-danger"></span>
                </div>
                <div class="form-group col-4">

                    <!--where the image should be desplayed-->
                    <img asp-for="<!--the route or the @Http.DisplayFor to bring the image?-->" alt="" class="img-fluid">

                </div>
            </div>        
        </form>

我真的不知道怎么做,我一直在看一些教程,几乎所有的教程都在img属性的源中放入了存储图像的文件夹的名称。

非常感谢任何帮助。

【问题讨论】:

  • 只需使用 HttpHandler 作为图像的来源,从数据库中拉取图像并返回。
  • @DaleK,感谢您的评论,我正在这样做,但 @HttpHandler 没有出现,它会引发错误。
  • 然后将该代码与错误一起添加到您的问题中。
  • 好吧,你建议使用@HttpHandler作为图像的来源,我做了以下:&lt;img src = "@HttpHandler ..." alt = "" class = "img-fluid"&gt;,但是在@HttpHandler中显示它在当前上下文中不存在。

标签: c# sql-server asp.net-mvc asp.net-core asp.net-core-webapi


【解决方案1】:

创建第二个ApiController 用于提供图片。

创建一个返回 HttpResponseMessage 的方法,并将图像的某种 ID 作为参数。

在该方法中构造一个响应并将内容设置为流。

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(...);

设置消息的 MIME 类型,可能是其中之一:

response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/svg+xml");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");

可选地设置一些标题来帮助缓存:

response.Headers.CacheControl = new CacheControlHeaderValue
{
    Public = true,
    MaxAge = TimeSpan.FromDays(30)
};

您的视图将需要生成一个指向第二个控制器/方法的img 标记。

【讨论】:

  • 别忘了设置mime类型:P。
  • @Aron,谢谢,在我从工作代码中复制粘贴时错过了这一点。
【解决方案2】:

您可以参考以下示例代码:

模型:在我的示例中,我通过 AppFile 将文件存储在数据库中,您可以将其更改为您的。

[注意]在您的示例中,模型名称为ContentForoModel,但在控制器中,模型名称为ForumContentModel,请检查您的代码并使用正确的模型。

public class AppFile
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte[] Content { get; set; }
}
public class ContentForoModel
{
    //some other fields
    //theme tables
    public string Content { get; set; }
    public byte[] ContentFile { get; set; } //this has the image
    public string FileType { get; set; }//the ext type of the image
    public string FileName { get; set; }//the name of the img

}

API控制器:根据ID查询数据库,返回指定模型。

[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    public TodoController(ApplicationDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    [Route("watchPost/{IdPost}")]
    public IActionResult watchPost(int IdPost)
    {
        ContentForoModel forum = new ContentForoModel();//this model is used to "join" various
                                                          //models

        //get the data from the different tables with the id sending from the MVC controller
        var appfile = _context.AppFiles.Where(x => x.Id == IdPost).FirstOrDefault();

        //Content data from the post

        forum.Content = appfile.Name;//the text part

        forum.ContentFile = appfile.Content;//the image
        return Ok(forum);
    }

MVC 控制器:您可以将 url 更改为您的。

    [HttpGet]
    public async Task<IActionResult> watchPost(int Id)
    {
        ContentForoModel forumModel = new ContentForoModel();
        if (Id == 0)
            Id = 1;
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://localhost:44310/api/todo/");

            var responseTask = client.GetAsync("watchPost/" + Id);

            responseTask.Wait();

            var result = responseTask.Result;

            if (result.IsSuccessStatusCode)
            {
                var apiResponse = await result.Content.ReadAsStringAsync();
                //required using Newtonsoft.Json;
                forumModel = JsonConvert.DeserializeObject<ContentForoModel>(apiResponse);
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Server error");
            }
        }

        return View(forumModel);
    }

查看页面:首先将字节数组转换为base64字符串,然后设置图片src属性。

@model WebApplication6.Models.ContentForoModel
 
<div class="row">
    <div class="col-md-4">
        <form asp-action="watchPost">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="row">
                <div class="form-group col-8">
                    <!--Text content-->
                    <label asp-for="Content" class="control-label h2"></label>
                    <textarea rows="4" asp-for="Content" class="form-control border-0" readonly="readonly"></textarea>
                    <span asp-validation-for="Content" class="text-danger"></span>
                </div>
                <div class="form-group col-4">
                    <label asp-for="ContentFile" class="control-label h2"></label>
                    @{
                        var base64 = Convert.ToBase64String(Model.ContentFile);
                        var Image = String.Format("data:image/gif;base64,{0}", base64);
                    }
                    <img src="@Image" alt="" class="img-fluid">
                </div>
            </div>
        </form>
    </div>
</div>

结果如下:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    相关资源
    最近更新 更多