从以二进制形式存储的Mssql服务器数据库中检索图像

时间:2019-07-03 12:34:54

标签: sql-server asp.net-core-mvc

我已经以二进制格式将jpeg文件存储在MSSql数据库中,现在我无法检索原始图像文件/ jpeg文件。有人可以帮我吗? 我已经使用ASP.net核心MVC将数据存储在数据库中。

ASP.net Core 2.2
MSSQL 2008
Visual Studio 2019

     [HttpGet]
      public IActionResult Index1()
     {
        var ab = _context.Movie.Select(a => a.File).Single();

        return View(ab);
     }

    // POST: api/Uploads
    [HttpPost]
       public IActionResult Post(Movie entity, IFormFile File)
      {
          using (var stream = new MemoryStream())
         {
            File.CopyTo(stream);
            entity.File = stream.ToArray();

        }

        _context.Movie.Add(entity);
        _context.SaveChanges();

        return Ok();
    }

 @model IEnumerable<FileUploads.Models.Movie>

@{
    ViewBag.Title = "Index1";
  }

 <h1>Index1</h1>
  <table>

    <tr>

      @foreach (var item in Model)
       {

          <td>

            @{ 


                var base64 = Convert.ToBase64String(item.File);
                var imgsrc = string.Format("data:image/jpeg;base64,{0}",  base64);
            }

            <img src='@imgsrc' style="max-height:100px;max-width:100px"/>
            }


</td>

        }

    </tr>

</table>
_________

这是我的post方法,get方法和查看页面的外观。

请帮助我。如何获取原始的JPEG格式图像?如果您还可以向我显示“查看页面”,将会很有帮助。

1 个答案:

答案 0 :(得分:0)

目前尚不清楚实际的问题是什么。您拥有的代码应该可以工作。

但是,无论如何,这都不是正确的方法,因此,与其浪费时间尝试调试它,不如简单地正确地做它。

使用数据URI的问题有两个:

  1. 您基本上是将图像嵌入HTML响应中,这意味着图像将非常大,并且可能需要很长时间才能下载。网络浏览器在收到完整的HTML文档之前无法开始呈现页面,因此该文档越大,则在进行有意义的绘画之前(即您将盯着空白屏幕)的时间越长。一幅图像可能还不错,但是如果您以这种方式添加的图像越多,问题就成倍地恶化。您的HTML文档最终可能会达到数兆字节的大小,尤其是对于移动数据而言,这是不好的。

  2. Base64是无效的编码。顾名思义,每个字节都由64个ASCII字符的组合表示。由于一个字节可以编码256个数字,因此最多需要4个字符(每个1-2个字节)来表示图像中的每个单独的字节。如果不清楚,则意味着您的图片大小将变为气球。正常运行50-60KB JPEG可能要花费240KB Base64编码的费用,这只会激怒首先描述的页面大小问题。

长短不一,这是通过操作为图像提供服务的正确方法。例如:

[HttpGet("movie-image/{movieId}")]
public async Task<IActionResult> MovieImage(int movieId)
{
    var movieImage = _context.Movie.Where(x => x.Id == movieId).Select(a => a.File).SingleOrDefault();
    if (movieImage == null)
        return NotFound();

    return File(movieImage, "image/jpeg");
}

然后,在您看来:

<img src="@Url.Action("MovieImage", new { movieId = item.Id })" />

您还可以考虑添加一些缓存头,以便浏览器缓存图像,并从缓存中加载图像,而不是将来每次显示时都击中服务器:

Response.Headers.Add(HeaderNames.CacheControl, $"max-age={TimeSpan.FromDays(365).TotalSeconds}");
return File(movieImage, "image/jpeg");

最后,由于将要缓存的URL与影片ID而不是物理图像相关联,因此,在需要更新图像的情况下,您可以考虑使用Etags。这有点高级,但并非绝对必要。最坏的情况是,如果用户以前已经下载了旧图像,则可能会从缓存中加载它。

无论如何,要生成Etag,您都需要生成图像字节的哈希值:

string checksum;
using (var sha256 = SHA256.Create())
{
    checksum = Convert.ToBase64String(sha256.ComputeHash(movieImage));
}

if (Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var etag && checksum == etag)
    return StatusCode((int)HttpStatusCode.NotModified);

Response.Headers.Add(HeaderNames.CacheControl, $"max-age={TimeSpan.FromDays(365).TotalSeconds}");
Response.Headers.Add(HeaderNames.Etag, checksum);
return File(movieImage, "image/jpeg");