Неясно, в чем собственно проблема. Код у вас должен работать.
Однако, это не правильный подход, поэтому вместо того, чтобы тратить время на его отладку, вы должны просто сделать это правильно.
Проблема с использованием URI данных имеет две стороны:
Вы в основном встраиваете изображение (и) в ответ HTML, что означает, что оно будет очень большим и потенциально может занять много времени для загрузки. Веб-браузер не может начать отображать страницу до тех пор, пока он не получит полный HTML-документ, поэтому чем больше этот документ, тем длиннее перед первой содержательной прорисовкой (т. Е. Вы будете смотреть на пустой экран). Одно изображение не может быть слишком плохим, но проблема становится экспоненциально хуже, чем больше вы добавляете таким образом. Ваш HTML-документ может иметь размер в мегабайтах, особенно с мобильными данными, что не очень хорошо.
Base64 - неэффективная кодировка. Как следует из названия, каждый байт представлен комбинацией из 64 символов ASCII. Поскольку байт может кодировать 256 чисел, для представления каждого отдельного байта в изображении требуется до 4 символов (по 1-2 байта каждый). В случае, если неясно, это означает, что размер вашего изображения будет вынос . Достойная работа мельницы JPEG размером 50-60 КБ может стоить целых 240 КБ в кодировке 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, который будет кэшироваться, привязан к идентификатору фильма, а не к физическому изображению, вы можете рассмотреть возможность использования 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");