Я работаю над серверным приложением Blazor, которое также включает минимальный API, который используется для нескольких задач, включая обслуживание запросов на файлы изображений, которые хранятся в базе данных, а не в файловой системе.
В целом все работает нормально. Моя единственная проблема заключается в том, что эти изображения никогда не кэшируются в браузере и не загружаются каждый раз, когда на странице используются соответствующие URL-адреса.
Маршрут для запроса GET прописан в Program.cs.
app.MapGet("/_image/{filename}", async ([FromRoute] string filename, FileService fileService) => await fileService.GetImage(filename));
Метод GetFile в FileService выглядит следующим образом:
public async Task<IResult> GetImage(string filename)
{
byte[] data = null;
if (!string.IsNullOrWhiteSpace(filename))
{
/* ... get data from database ... */
}
return data != null ? Results.File(data, "image/png", filename) : Results.NotFound();
}
Таким образом, всякий раз, когда запрос к одному из этих файлов включается в тег изображения (например, <img src = "/_image/test.png"/>
), изображение отображается. Но всякий раз, когда страница открывается, изображение загружается снова, вместо того, чтобы использовать его из кеша браузера.
Итак, как я могу указать браузеру кэшировать изображение?
Вторая проблема, которую я заметил: когда я ввожу URL-адрес изображения в поле адреса браузера (например, http://server.com/_image/test.png), изображение всегда загружается напрямую в файл загрузки. папка вместо того, чтобы отображаться в окне браузера. Для меня это на данный момент не проблема, но просто из любопытства, что мне нужно изменить, чтобы изображение показывалось?
ОБНОВЛЯТЬ:
Я решил обе проблемы с небольшими изменениями. Мне пришлось добавить HttpContext, который дает доступ к ответу.
В Program.cs
app.MapGet("/_image/{filename}", async ([FromRoute] string filename, FileService fileService, HttpContext context) => await fileService.GetImage(filename, context));
и для метода получения файла и отправки ответа
public async Task<IResult> GetImage(string filename, HttpContext context)
{
byte[] data = null;
if (!string.IsNullOrWhiteSpace(filename))
{
/* ... get data from database ... */
if (data != null) {
context.Response.Headers.ContentDisposition = "inline";
context.Response.Headers.CacheControl = "max-age=180, public";
}
}
return data != null ? Results.File(data, "image/png", filename) : Results.NotFound();
}
Теперь он работает отлично.
да, было полезно. вместе с ответом @MxNbrt я мог бы решить обе проблемы. смотрите обновления выше. Спасибо.
Что касается первой проблемы (кэширование), вы можете прочитать все о различных проблемах ASP.NET Core здесь: https://learn.microsoft.com/en-us/aspnet/core/ Performance/caching/overview? view=aspnetcore-8.0 (думаю, вам захочется использовать кэширование ответов)
По поводу второй проблемы (загрузка) посмотрите здесь https://stackoverflow.com/a/51216687/7291459. Поведение регулируется заголовком Content-Disposition, для которого можно установить значение inline
(показать как изображение) или attachment
(загрузить).
Спасибо за эти подсказки, которые наконец указали мне правильное направление. см. обновление исходного вопроса.
Может быть полезно: stackoverflow.com/a/73582792/199364