У меня есть ASP. NET Базовый веб-API, называемый «хранилище», написанный с использованием C#
. Это приложение предназначено для обслуживания многих веб-приложений с изображениями. Используя другие имеющиеся у меня приложения, я могу запрашивать изображения из хранилища, используя HTTP-запрос.
Чтобы взаимодействовать с моим приложением хранилища из вторичного / потребляющего приложения, я создал собственную реализацию провайдера файлов, которая позволила бы мне получить доступ к этим такие изображения
public class MyCustomImagesProvider : IFileProvider
{
private readonly IHttpClientFactory ClientFactory;
public MyCustomImagesProvider(IHttpClientFactory clientFactory)
{
ClientFactory = clientFactory;
}
public IFileInfo GetFileInfo(string subpath)
{
try
{
var client = ClientFactory.CreateClient("client-name");
Uri url = new Uri("https://storage.mydomain.com", $"api/files/get?name={subpath}");
var result = client.GetAsync(url).Result;
result.EnsureSuccessStatusCode();
string filename = Path.GetFileName(subpath);
DateTime lastModifiedAt = (result.Content.Headers.LastModified?.DateTime) ?? DateTime.Now;
var stream = result.Content.ReadAsStreamAsync().Result;
return new MyCustomFileInfo(stream, filename, lastModifiedAt);
}
catch
{
}
return new MyCustomFileInfo
{
Exists = false
};
}
public IDirectoryContents GetDirectoryContents(string subpath) => throw new NotImplementedException();
public IChangeToken Watch(string filter) => throw new NotImplementedException();
}
В некоторых из моих приложений требуется только миниатюра изображения, тогда как для других требуется полный размер и / или миниатюра изображения. Позже мне может даже понадобиться изображение среднего размера для некоторых приложений (возможно, 4 разных размера одного и того же изображения). Ограничение дискового пространства становится проблемой, поскольку мне приходится дублировать одно и то же изображение на несколько файлов (по одному для каждого размера) для размещения всех моих приложений.
Другими словами, если у меня есть файл с именем "abc_fullsize.jpg", то мне нужно будет создать и сохранить "abc_thumbnail.jpg" и "abc_midside.jpg", для которых требуется много места на диске.
Вопрос
Было бы целесообразно создавать эти изображения на лету вместо того, чтобы создавать их на столе?
Я думаю, у меня будет ThumbnailImageProvider
, MidsizeImageProvider
и FullsizeImageProvider
, каждый из которых отправит требуемый максимальный размер для приложения хранения, а приложение хранения будет считывать полноразмерное изображение со стола и затем отвечать измененным размером образ. Вот пример ThumbnailImageProvider
public class ThumbnailImageProvider : IFileProvider
{
private readonly IHttpClientFactory ClientFactory;
public ThumbnailImageProvider(IHttpClientFactory clientFactory)
{
ClientFactory = clientFactory;
}
public IFileInfo GetFileInfo(string subpath)
{
try
{
var client = ClientFactory.CreateClient("client-name");
// Note the max-width=250 parameter here would tell the API that I need this image recreated on the fly with max width of 250.
Uri url = new Uri("https://storage.mydomain.com", $"api/files/get?name={subpath}&maxWidth=250");
var result = client.GetAsync(url).Result;
result.EnsureSuccessStatusCode();
string filename = Path.GetFileName(subpath);
DateTime lastModifiedAt = (result.Content.Headers.LastModified?.DateTime) ?? DateTime.Now;
var stream = result.Content.ReadAsStreamAsync().Result;
return new MyCustomFileInfo(stream, filename, lastModifiedAt);
}
catch
{
}
return new MyCustomFileInfo
{
Exists = false
};
}
public IDirectoryContents GetDirectoryContents(string subpath) => throw new NotImplementedException();
public IChangeToken Watch(string filter) => throw new NotImplementedException();
}
Метод действия на конечной точке api/files/get
ответит следующим действием
[HttpGet("get")]
public IActionResult Get(string name, int? maxWidth)
{
IFileInfo fileInfo = FileProvider.GetFileInfo(name);
if (!fileInfo.Exists)
{
return NotFound();
}
if(maxWidth.HasValue && maxWidth > 1)
{
Image image = ImageProcessor.GetResizedImage(fileInfo.CreateReadStream(), maxWidth.Value, out ImageFormat imageFormat);
using var memoryStream = new MemoryStream();
image.Save(memoryStream, imageFormat);
string extension = Path.GetExtension(fileInfo.Name);
string rawFilename = Path.GetFileNameWithoutExtension(fileInfo.Name);
string filename = $"{rawFilename}-{maxWidth}{extension}";
return File(memoryStream, "image/jpeg", filename, fileInfo.LastModified, null);
}
return File(fileInfo.CreateReadStream(), "image/jpeg", fileInfo.Name, fileInfo.LastModified, null);
}