[英]Image provider in ASP.NET Core 3.1
I have an ASP.NET Core based web-API called "storage" written using C#
.我有一个基于 ASP.NET Core 的名为“存储”的 Web API,使用C#
编写。 This app is designed to serve many web-apps with images.此应用程序旨在为许多带有图像的网络应用程序提供服务。 Using other apps I have can request images from the storage using an HTTP request.使用我拥有的其他应用程序可以使用 HTTP 请求从存储中请求图像。
To interact with my storage app from a secondary/consuming app, I created a custom file-provider implementation that would allow me to access these images like so为了从辅助/消费应用程序与我的存储应用程序交互,我创建了一个自定义文件提供程序实现,它允许我像这样访问这些图像
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();
}
Some of my apps require only the thumbnail of the image where others require a full-size and/or thumbnail of the image.我的一些应用程序只需要图像的缩略图,而其他应用程序需要图像的全尺寸和/或缩略图。 Later, I may even need a mid-size image too for some apps (possibly 4 different sizes of the same image.) Diskspace limitation is becoming an issue since I am having to duplicate the same image into multiple files (one for each size) to accommodate all of my apps.后来,对于某些应用程序,我什至可能还需要一个中等大小的图像(同一图像可能有 4 个不同大小的图像。)磁盘空间限制正在成为一个问题,因为我必须将同一个图像复制到多个文件中(每个文件一个)以容纳我所有的应用程序。
In other words, if I have a file called "abc_fullsize.jpg" then I would need to create and store "abc_thumbnail.jpg", and "abc_midside.jpg" which requires lots of disk space.换句话说,如果我有一个名为“abc_fullsize.jpg”的文件,那么我需要创建和存储“abc_thumbnail.jpg”和“abc_midside.jpg”,这需要大量磁盘空间。
Question题
Would it be efficient to create these images on the fly instead of having to create them on the desk?动态创建这些图像而不是在桌面上创建它们是否有效?
I am thinking I would have a ThumbnailImageProvider
, MidsizeImageProvider
and FullsizeImageProvider
each would send required max-size for the storage app and the storage app would read the full-size image from the desk and then respond with the resized image.我想我将有一个ThumbnailImageProvider
, MidsizeImageProvider
和FullsizeImageProvider
每个就送需要最大尺寸为存储应用程序和存储的应用程序将读取来自台全尺寸的图像,然后用调整后的图像响应。 Here would be an example of the ThumbnailImageProvider
这是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();
}
The action method on the api/files/get
endpoint will respond with the following action 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);
}
I would think that you would be better off applying your logic to a middleware.我认为您最好将您的逻辑应用于中间件。 Have a look at how aspnet's static file middle ware works:看看aspnet的静态文件中间件是如何工作的:
https://github.com/dotnet/aspnetcore/blob/19d2f6124f5d04859e350d1f5a01e994e14ef1ce/src/Middleware/StaticFiles/src/StaticFileMiddleware.cs https://github.com/dotnet/aspnetcore/blob/19d2f6124f5d04859e350d1f5a01e994e14ef1ce/src/Middleware/StaticFiles/src/StaticFileMiddleware.cs
There are two concerns with your approach:你的方法有两个问题:
So my recommendation would be to cache images on disk (or the blob storage while using output cache) -> https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1所以我的建议是在磁盘上缓存图像(或使用输出缓存时的 blob 存储)-> https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore- 3.1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.