添加缩略图同步功能

This commit is contained in:
橙子
2022-10-17 01:10:31 +08:00
parent 50d43a2fc5
commit 16d25fb60d
23 changed files with 568 additions and 136 deletions

View File

@@ -270,29 +270,37 @@
文件
</summary>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.#ctor(Yi.Framework.Interface.IFileService,Microsoft.Extensions.Hosting.IHostEnvironment)">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.#ctor(Yi.Framework.Interface.IFileService,Microsoft.Extensions.Hosting.IHostEnvironment,Yi.Framework.Core.ThumbnailSharpInvoer)">
<summary>
文件上传下载
</summary>
<param name="iFileService"></param>
<param name="env"></param>
<param name="thumbnailSharpInvoer"></param>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.Get(System.Int64)">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.Get(System.Int64,System.Nullable{System.Boolean})">
<summary>
文件下载,只需用文件code即可
文件下载,只需用文件code即可,可选择是否为缩略图
</summary>
<param name="code"></param>
<param name="isThumbnail"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.Upload(System.String,Microsoft.AspNetCore.Http.IFormFileCollection,System.String)">
<summary>
多文件上传,type可空默认上传至File文件夹下swagger返回雪花id精度是有问题的
多文件上传,type可空默认上传至File文件夹下swagger返回雪花id精度是有问题的,同时如果时图片类型,还需要进行缩略图制作
</summary>
<param name="type">文件类型,可空</param>
<param name="file">多文件表单</param>
<param name="remark">描述</param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.FileController.ThumbnailSync">
<summary>
一键同步图片到缩略图
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.LogController.Add">
<summary>
自动分表,日志添加
@@ -438,7 +446,7 @@
测试控制器
</summary>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.#ctor(Microsoft.AspNetCore.SignalR.IHubContext{Yi.Framework.WebCore.SignalRHub.MainHub},Microsoft.Extensions.Logging.ILogger{Yi.Framework.Model.Models.UserEntity},Yi.Framework.Interface.IRoleService,Yi.Framework.Interface.IUserService,Microsoft.Extensions.Localization.IStringLocalizer{Yi.Framework.Language.LocalLanguage},Yi.Framework.Core.QuartzInvoker)">
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.#ctor(Microsoft.AspNetCore.SignalR.IHubContext{Yi.Framework.WebCore.SignalRHub.MainHub},Microsoft.Extensions.Logging.ILogger{Yi.Framework.Model.Models.UserEntity},Yi.Framework.Interface.IRoleService,Yi.Framework.Interface.IUserService,Microsoft.Extensions.Localization.IStringLocalizer{Yi.Framework.Language.LocalLanguage},Yi.Framework.Core.QuartzInvoker,Yi.Framework.Core.ThumbnailSharpInvoer)">
<summary>
依赖注入
</summary>
@@ -448,6 +456,7 @@
<param name="iUserService"></param>
<param name="local"></param>
<param name="quartzInvoker"></param>
<param name="thumbnailSharpInvoer"></param>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.Swagger">
<summary>
@@ -547,6 +556,12 @@
<param name="msg"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.ThumbnailTest">
<summary>
缩略图测试,需要生成前及生成后的路径
</summary>
<returns></returns>
</member>
<member name="T:Yi.Framework.ApiMicroservice.Controllers.UserController">
<summary>
用户管理

View File

@@ -11,7 +11,9 @@ using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common.Const;
using Yi.Framework.Common.Enum;
using Yi.Framework.Common.Helper;
using Yi.Framework.Common.Models;
using Yi.Framework.Core;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.WebCore;
@@ -27,26 +29,30 @@ namespace Yi.Framework.ApiMicroservice.Controllers
{
private IFileService _iFileService;
private readonly IHostEnvironment _env;
private ThumbnailSharpInvoer _thumbnailSharpInvoer;
/// <summary>
/// 文件上传下载
/// </summary>
/// <param name="iFileService"></param>
/// <param name="env"></param>
public FileController(IFileService iFileService, IHostEnvironment env)
/// <param name="thumbnailSharpInvoer"></param>
public FileController(IFileService iFileService, IHostEnvironment env, ThumbnailSharpInvoer thumbnailSharpInvoer)
{
_iFileService = iFileService;
_env = env;
_thumbnailSharpInvoer = thumbnailSharpInvoer;
}
/// <summary>
/// 文件下载,只需用文件code即可
/// 文件下载,只需用文件code即可,可选择是否为缩略图
/// </summary>
/// <param name="code"></param>
/// <param name="isThumbnail"></param>
/// <returns></returns>
[Route("/api/file/{code}")]
[Route("/api/file/{code}/{isThumbnail?}")]
[HttpGet]
public async Task<IActionResult> Get(long code)
public async Task<IActionResult> Get(long code, bool? isThumbnail)
{
var file = await _iFileService._repository.GetByIdAsync(code);
if (file is null)
@@ -55,6 +61,11 @@ namespace Yi.Framework.ApiMicroservice.Controllers
}
try
{
//如果为缩略图
if (isThumbnail is true)
{
file.FilePath = PathEnum.Thumbnail.ToString();
}
//路径为: 文件路径/文件id+文件扩展名
var path = Path.Combine($"{PathConst.wwwroot}/{file.FilePath}", file.Id.ToString() + Path.GetExtension(file.FileName));
var stream = System.IO.File.OpenRead(path);
@@ -68,7 +79,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
}
/// <summary>
/// 多文件上传,type可空默认上传至File文件夹下swagger返回雪花id精度是有问题的
/// 多文件上传,type可空默认上传至File文件夹下swagger返回雪花id精度是有问题的,同时如果时图片类型,还需要进行缩略图制作
/// </summary>
/// <param name="type">文件类型,可空</param>
/// <param name="file">多文件表单</param>
@@ -117,10 +128,30 @@ namespace Yi.Framework.ApiMicroservice.Controllers
{
Directory.CreateDirectory(typePath);
}
using (var stream = new FileStream(Path.Combine(typePath, filename), FileMode.CreateNew, FileAccess.Write))
//生成文件
using (var stream = new FileStream(Path.Combine(typePath, filename), FileMode.CreateNew, FileAccess.ReadWrite))
{
await f.CopyToAsync(stream);
}
//如果是图片类型,还需要生成缩略图
if (PathEnum.Image.ToString().Equals(type))
{
//保存至缩略图路径
var result = _thumbnailSharpInvoer.CreateThumbnailBytes(thumbnailSize: 300,
imageStream: stream,
imageFormat: Format.Jpeg);
string thumbnailPath = $"{PathConst.wwwroot}/{PathEnum.Thumbnail}";
if (!Directory.Exists(thumbnailPath))
{
Directory.CreateDirectory(thumbnailPath);
}
await System.IO.File.WriteAllBytesAsync(Path.Combine(thumbnailPath, filename), result);
}
};
//将文件信息添加到数据库
datas.Add(data);
codes.Add(data.Id);
@@ -132,5 +163,44 @@ namespace Yi.Framework.ApiMicroservice.Controllers
return Result.Error();
}
}
/// <summary>
/// 一键同步图片到缩略图
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<Result> ThumbnailSync()
{
string typePath = $"{PathConst.wwwroot}/{PathEnum.Image}";
string thumbnailPath = $"{PathConst.wwwroot}/{PathEnum.Thumbnail}";
List<string> fileNames =FileHelper. GetAllFileNames(typePath);
foreach (var filename in fileNames)
{
if (System.IO.File.Exists(Path.Combine(thumbnailPath, filename)))
{
//如果缩略图存在,直接跳过
continue;
}
if (!Directory.Exists(typePath))
{
Directory.CreateDirectory(typePath);
}
using (var stream = new FileStream(Path.Combine(typePath, filename), FileMode.Open, FileAccess.ReadWrite))
{
//保存至缩略图路径
var result = _thumbnailSharpInvoer.CreateThumbnailBytes(thumbnailSize: 300,
imageStream: stream,
imageFormat: Format.Jpeg);
if (!Directory.Exists(thumbnailPath))
{
Directory.CreateDirectory(thumbnailPath);
}
await System.IO.File.WriteAllBytesAsync(Path.Combine(thumbnailPath, filename), result);
};
}
return Result.Success();
}
}
}

View File

@@ -35,6 +35,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
private IRoleService _iRoleService;
private QuartzInvoker _quartzInvoker;
private IHubContext<MainHub> _hub;
private ThumbnailSharpInvoer _thumbnailSharpInvoer;
//你可以依赖注入服务层各各接口,也可以注入其他仓储层,怎么爽怎么来!
/// <summary>
/// 依赖注入
@@ -45,13 +46,15 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// <param name="iUserService"></param>
/// <param name="local"></param>
/// <param name="quartzInvoker"></param>
public TestController(IHubContext<MainHub> hub , ILogger<UserEntity> logger, IRoleService iRoleService, IUserService iUserService, IStringLocalizer<LocalLanguage> local, QuartzInvoker quartzInvoker)
/// <param name="thumbnailSharpInvoer"></param>
public TestController(IHubContext<MainHub> hub, ILogger<UserEntity> logger, IRoleService iRoleService, IUserService iUserService, IStringLocalizer<LocalLanguage> local, QuartzInvoker quartzInvoker, ThumbnailSharpInvoer thumbnailSharpInvoer)
{
_iUserService = iUserService;
_iRoleService = iRoleService;
_quartzInvoker = quartzInvoker;
_hub = hub;
_local = local;
_thumbnailSharpInvoer = thumbnailSharpInvoer;
}
/// <summary>
@@ -266,7 +269,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// </summary>
/// <returns></returns>
[HttpGet]
public Result SeedDb()
public Result SeedDb()
{
var rep = _iUserService._repository;
return Result.Success().SetStatus(DbSeedExtend.Invoer(rep._Db));
@@ -290,11 +293,33 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// <param name="msg"></param>
/// <returns></returns>
[HttpGet]
public async Task<Result> SignalrTest(int msg)
public async Task<Result> SignalrTest(int msg)
{
await _hub.Clients.All.SendAsync("onlineNum", msg);
return Result.Success("向所有连接客户端发送一个消息");
}
//job任务与公告管理
/// <summary>
/// 缩略图测试,需要生成前及生成后的路径
/// </summary>
/// <returns></returns>
[HttpGet]
public Result ThumbnailTest()
{
try
{
var path = @"D:\App\test11.jpg";
var result = _thumbnailSharpInvoer.CreateThumbnailBytes(thumbnailSize: 300,
imageStream: new FileStream(path, FileMode.Open, FileAccess.ReadWrite),
imageFormat: Format.Jpeg);
System.IO.File.WriteAllBytes(@"D:\App\test222.jpg", result);
}
catch (Exception ex)
{
return Result.Error(ex.Message);
}
return Result.Success();
}
}
}

View File

@@ -137,8 +137,11 @@ builder.Services.AddHeiCaptcha();
#region
//<2F><><EFBFBD><EFBFBD>Http<74><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion
builder.Services.AddHttpContextAccessor();
#region
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
#endregion
builder.Services.AddSingleton<ThumbnailSharpInvoer>();
//-----------------------------------------------------------------------------------------------------------
var app = builder.Build();
#region

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -11,6 +11,7 @@ namespace Yi.Framework.Common.Enum
Excel,
File,
Image,
Thumbnail,
Temp
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
@@ -10,6 +11,8 @@ namespace Yi.Framework.Common.Helper
private bool _alreadyDispose = false;
#region
public FileHelper()
{
@@ -391,5 +394,19 @@ namespace Yi.Framework.Common.Helper
}
}
#endregion
/// <summary>
/// 获取目录下全部文件名
/// </summary>
/// <param name="path"></param>
/// <param name="pattern"></param>
/// <returns></returns>
public static List<string> GetAllFileNames(string path, string pattern = "*")
{
List<FileInfo> folder = new DirectoryInfo(path).GetFiles(pattern).ToList();
return folder.Select(x => x.Name).ToList();
}
}
}

View File

@@ -12,7 +12,7 @@ using CSRedis;
namespace Yi.Framework.Core
{
public class CacheClientDB
public class CacheInvoker
{
public delegate T MyAction<T>(CSRedisClient client);
@@ -22,7 +22,7 @@ namespace Yi.Framework.Core
private CSRedisClient Client { get; set; }
public CSRedisClient _Db { get { return Client; } set { } }
public CacheClientDB(IOptionsMonitor<RedisConnOptions> redisConnOptions)
public CacheInvoker(IOptionsMonitor<RedisConnOptions> redisConnOptions)
{
this._RedisOptions = redisConnOptions.CurrentValue;
Client = new CSRedisClient($"{_RedisOptions.Host}:{_RedisOptions.Prot},password={_RedisOptions.Password},defaultDatabase ={ _RedisOptions.DB }");

View File

@@ -0,0 +1,410 @@
/*MIT License
Copyright(c) 2017 Mirza Ghulam Rasyid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace Yi.Framework.Core
{
/// <summary>
/// Image format to use when creating a thumbnail.
/// </summary>
public enum Format
{
Jpeg,
Bmp,
Png,
Gif,
Tiff
}
/// <summary>
/// Thumbnail class that holds various methods to create an image thumbnail.
/// </summary>
public class ThumbnailSharpInvoer
{
private Bitmap CreateBitmapThumbnail(uint thumbnailSize, string imageFileLocation)
{
Bitmap bitmap = null;
Image image = null;
float actualHeight = default(float);
float actualWidth = default(float);
uint thumbnailHeight = default(uint);
uint thumbnailWidth = default(uint);
try
{
image = Image.FromFile(imageFileLocation);
}
catch
{
if (image != null)
image = null;
}
if (image != null)
{
actualHeight = image.Height;
actualWidth = image.Width;
if (actualHeight > actualWidth)
{
if ((uint)actualHeight <= thumbnailSize)
throw new Exception("Thumbnail size must be less than actual height (portrait image)");
thumbnailHeight = thumbnailSize;
thumbnailWidth = (uint)((actualWidth / actualHeight) * thumbnailSize);
}
else if (actualWidth > actualHeight)
{
if ((uint)actualWidth <= thumbnailSize)
throw new Exception("Thumbnail size must be less than actual width (landscape image)");
thumbnailWidth = thumbnailSize;
thumbnailHeight = (uint)((actualHeight / actualWidth) * thumbnailSize);
}
else
{
if ((uint)actualWidth <= thumbnailSize)
throw new Exception("Thumbnail size must be less than image's size");
thumbnailWidth = thumbnailSize;
thumbnailHeight = thumbnailSize;
}
try
{
bitmap = new Bitmap((int)thumbnailWidth, (int)thumbnailHeight);
Graphics resizedImage = Graphics.FromImage(bitmap);
resizedImage.InterpolationMode = InterpolationMode.HighQualityBicubic;
resizedImage.CompositingQuality = CompositingQuality.HighQuality;
resizedImage.SmoothingMode = SmoothingMode.HighQuality;
resizedImage.DrawImage(image, 0, 0, thumbnailWidth, thumbnailHeight);
}
catch
{
if (bitmap != null)
bitmap = null;
}
}
return bitmap;
}
private Bitmap CreateBitmapThumbnail(uint thumbnailSize, Stream imageStream)
{
Bitmap bitmap = null;
Image image = null;
float actualHeight = default(float);
float actualWidth = default(float);
uint thumbnailHeight = default(uint);
uint thumbnailWidth = default(uint);
try
{
image = Image.FromStream(imageStream);
}
catch
{
if (image != null)
image = null;
}
if (image != null)
{
actualHeight = image.Height;
actualWidth = image.Width;
if (actualHeight > actualWidth)
{
if ((uint)actualHeight <= thumbnailSize)
throw new Exception("Thumbnail size must be less than actual height (portrait image)");
thumbnailHeight = thumbnailSize;
thumbnailWidth = (uint)((actualWidth / actualHeight) * thumbnailSize);
}
else if (actualWidth > actualHeight)
{
if ((uint)actualWidth <= thumbnailSize)
throw new Exception("Thumbnail size must be less than actual width (landscape image)");
thumbnailWidth = thumbnailSize;
thumbnailHeight = (uint)((actualHeight / actualWidth) * thumbnailSize);
}
else
{
if ((uint)actualWidth <= thumbnailSize)
throw new Exception("Thumbnail size must be less than image's size");
thumbnailWidth = thumbnailSize;
thumbnailHeight = thumbnailSize;
}
try
{
bitmap = new Bitmap((int)thumbnailWidth, (int)thumbnailHeight);
Graphics resizedImage = Graphics.FromImage(bitmap);
resizedImage.InterpolationMode = InterpolationMode.HighQualityBicubic;
resizedImage.CompositingQuality = CompositingQuality.HighQuality;
resizedImage.SmoothingMode = SmoothingMode.HighQuality;
resizedImage.DrawImage(image, 0, 0, thumbnailWidth, thumbnailHeight);
}
catch
{
if (bitmap != null)
bitmap = null;
}
}
return bitmap;
}
private ImageFormat GetImageFormat(Format format)
{
switch (format)
{
case Format.Jpeg:
return ImageFormat.Jpeg;
case Format.Bmp:
return ImageFormat.Bmp;
case Format.Png:
return ImageFormat.Png;
case Format.Gif:
return ImageFormat.Gif;
default:
return ImageFormat.Tiff;
}
}
private async Task<Stream> GetImageStreamFromUrl(Uri urlAddress)
{
Stream result = null;
try
{
byte[] bytes = await GetImageBytesFromUrl(urlAddress);
result = new MemoryStream(bytes);
}
catch
{
result = null;
}
return result;
}
private async Task<byte[]> GetImageBytesFromUrl(Uri urlAddress)
{
byte[] buffer = null;
try
{
using (HttpClient client = new HttpClient())
{
buffer = await client.GetByteArrayAsync(urlAddress);
}
}
catch
{
buffer = null;
}
return buffer;
}
/// <summary>
/// Create a thumbnail from file and returns as stream.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageFileLocation">Correct image file location.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as stream. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageFileLocation' is null.</exception>
/// <exception cref="FileNotFoundException">'imageFileLocation' does not exist.</exception>
public Stream CreateThumbnailStream(uint thumbnailSize, string imageFileLocation, Format imageFormat)
{
if (String.IsNullOrEmpty(imageFileLocation))
throw new ArgumentNullException(nameof(imageFileLocation), "'imageFileLocation' cannot be null");
if (!File.Exists(imageFileLocation))
throw new FileNotFoundException($"'{imageFileLocation}' cannot be found");
Bitmap bitmap = CreateBitmapThumbnail(thumbnailSize, imageFileLocation);
if (bitmap != null)
{
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, GetImageFormat(imageFormat));
stream.Position = 0;
return stream;
}
return null;
}
/// <summary>
/// Create a thumbnail from image stream and returns as stream.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageStream">Valid image stream object.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as stream. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageStream' is null.</exception>
public Stream CreateThumbnailStream(uint thumbnailSize, Stream imageStream, Format imageFormat)
{
if (imageStream == null)
throw new ArgumentNullException(nameof(imageStream), "'imageStream' cannot be null");
Bitmap bitmap = CreateBitmapThumbnail(thumbnailSize, imageStream);
if (bitmap != null)
{
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, GetImageFormat(imageFormat));
stream.Position = 0;
return stream;
}
return null;
}
/// <summary>
/// Create a thumbnail from image in bytes and returns as stream.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageBytes">Valid image bytes array.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as stream. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageBytes' is null.</exception>
public Stream CreateThumbnailStream(uint thumbnailSize, byte[] imageBytes, Format imageFormat)
{
if (imageBytes == null)
throw new ArgumentNullException(nameof(imageBytes), "'imageStream' cannot be null");
Bitmap bitmap = CreateBitmapThumbnail(thumbnailSize, new MemoryStream(imageBytes));
if (bitmap != null)
{
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, GetImageFormat(imageFormat));
stream.Position = 0;
return stream;
}
return null;
}
/// <summary>
/// Create a thumbnail from file and returns as bytes.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageFileLocation">Correct image file location.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as bytes. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageFileLocation' is null.</exception>
/// <exception cref="FileNotFoundException">'imageFileLocation' does not exist.</exception>
public byte[] CreateThumbnailBytes(uint thumbnailSize, string imageFileLocation, Format imageFormat)
{
if (String.IsNullOrEmpty(imageFileLocation))
throw new ArgumentNullException(nameof(imageFileLocation), "'imageFileLocation' cannot be null");
if (!File.Exists(imageFileLocation))
throw new FileNotFoundException($"'{imageFileLocation}' cannot be found");
Stream stream = CreateThumbnailStream(thumbnailSize, imageFileLocation, imageFormat);
if (stream != null)
{
byte[] streamBytes = new byte[stream.Length];
stream.Read(streamBytes, 0, streamBytes.Length);
return streamBytes;
}
return null;
}
/// <summary>
/// Create a thumbnail from image stream and returns as bytes.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageStream">Valid image stream object.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as bytes. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageStream' is null.</exception>
public byte[] CreateThumbnailBytes(uint thumbnailSize, Stream imageStream, Format imageFormat)
{
if (imageStream == null)
throw new ArgumentNullException(nameof(imageStream), "'imageStream' cannot be null");
Stream stream = CreateThumbnailStream(thumbnailSize, imageStream, imageFormat);
if (stream != null)
{
byte[] streamBytes = new byte[stream.Length];
stream.Read(streamBytes, 0, streamBytes.Length);
return streamBytes;
}
return null;
}
/// <summary>
/// Create a thumbnail from image in bytes and returns as bytes.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="imageBytes">Valid image bytes array.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as bytes. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'imageBytes' is null.</exception>
public byte[] CreateThumbnailBytes(uint thumbnailSize, byte[] imageBytes, Format imageFormat)
{
if (imageBytes == null)
throw new ArgumentNullException(nameof(imageBytes), "'imageStream' cannot be null");
Stream stream = CreateThumbnailStream(thumbnailSize, imageBytes, imageFormat);
if (stream != null)
{
byte[] streamBytes = new byte[stream.Length];
stream.Read(streamBytes, 0, streamBytes.Length);
return streamBytes;
}
return null;
}
/// <summary>
/// Create a thumbnail from valid image url asynchronously.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="urlAddress">Valid absolute url address with proper scheme.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as stream. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'urlAddress' is null.</exception>
public async Task<Stream> CreateThumbnailStreamAsync(uint thumbnailSize, Uri urlAddress, Format imageFormat)
{
if (urlAddress == null)
throw new ArgumentNullException(nameof(urlAddress), "'urlAddress' cannot be null");
Stream result = null;
Stream stream = await GetImageStreamFromUrl(urlAddress);
if (stream != null)
{
result = CreateThumbnailStream(thumbnailSize, stream, imageFormat);
}
return result;
}
/// <summary>
/// Create a thumbnail from valid image url asynchronously.
/// </summary>
/// <param name="thumbnailSize">Thumbnail size. For portrait image, thumbnail size must be less than its height.
/// For landscape image, thumbnail size must be less than its width. For the same size image (Proportional), thumbnail size must be less than its width and height.</param>
/// <param name="urlAddress">Valid absolute url address with proper scheme.</param>
/// <param name="imageFormat">Image format to use.</param>
/// <returns>A thumbnail image as bytes. Returns null if it fails.</returns>
/// <exception cref="ArgumentNullException">'urlAddress' is null.</exception>
public async Task<byte[]> CreateThumbnailBytesAsync(uint thumbnailSize, Uri urlAddress, Format imageFormat)
{
if (urlAddress == null)
throw new ArgumentNullException(nameof(urlAddress), "'urlAddress' cannot be null");
byte[] result = null;
byte[] imageBytes = await GetImageBytesFromUrl(urlAddress);
if (imageBytes != null)
{
result = CreateThumbnailBytes(thumbnailSize, imageBytes, imageFormat);
}
return result;
}
}
}

View File

@@ -1,109 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Model.Models;
namespace Yi.Framework.Core
{
public static class TreeMenuBuild
{
// /// <summary>
// /// 过滤所有已经删除的菜单
// /// </summary>
// /// <param name="menu_data"></param>
// /// <returns></returns>
// public static menu Normal(menu menu_data)
// {
// for (int i = menu_data.children.Count() - 1; i >= 0; i--)
// {
// if (menu_data.children[i].is_delete == (short)Common.Enum.DelFlagEnum.Deleted)
// {
// menu_data.children.Remove(menu_data.children[i]);
// }
// else if (menu_data.children[i] != null)
// {
// Normal(menu_data.children[i]);
// }
// }
// return menu_data;
// }
// public static menu ShowFormat(menu menu_data, List<int> allMenuIds)
// {
// return Format(Show(menu_data, allMenuIds));
// }
// /// <summary>
// /// 过滤用户不展示及已删除及未拥有的菜单
// /// </summary>
// /// <param name="menu_data"></param>
// /// <param name="allMenuIds"></param>
// /// <returns></returns>
// private static menu Show(menu menu_data, List<int> allMenuIds)
// {
// for (int i = menu_data.children.Count() - 1; i >= 0; i--)
// {
// if (!allMenuIds.Contains(menu_data.children[i].id) || menu_data.children[i].is_delete == (short)Common.Enum.DelFlagEnum.Deleted || menu_data.children[i].is_show == (short)Common.Enum.ShowFlagEnum.NoShow)
// {
// menu_data.children.Remove(menu_data.children[i]);
// }
// else
// {
// Show(menu_data.children[i], allMenuIds);
// }
// }
// return menu_data;
// }
// /// <summary>
// /// 为了匹配前端格式通常和show方法一起
// /// </summary>
// /// <param name="menu_data"></param>
// /// <returns></returns>
// private static menu Format(menu menu_data)
// {
// for (int i = menu_data.children.Count() - 1; i >= 0; i--)
// {
// if (menu_data.children[i].icon == null)
// {
// menu_data.children[i].icon = "mdi-view-dashboard";
// }
// if (menu_data.children != null || menu_data.children.Count() != 0)
// {
// Format(menu_data.children[i]);
// }
// }
// if (menu_data.children.Count() == 0)
// {
// menu_data.children = null;
// }
// return menu_data;
// }
// public static menu Sort(menu menu_data)
// {
// if (menu_data.children != null)
// {
// for (int i = menu_data.children.Count() - 1; i >= 0; i--)
// {
// menu_data.children = menu_data.children.AsEnumerable().OrderByDescending(u => u.sort).ToList();
// if (menu_data.children != null || menu_data.children.Count() != 0)
// {
// Sort(menu_data.children[i]);
// }
// }
// }
// return menu_data;
// }
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>

View File

@@ -37,7 +37,7 @@ namespace Yi.Framework.OcelotGateway.Builder
public HttpContext? Context { get; set; }
public CacheClientDB? DB { get; set; }
public CacheInvoker? DB { get; set; }
}
}

View File

@@ -12,8 +12,8 @@ namespace Yi.Framework.OcelotGateway.WebCore
public class OcelotMiddleware
{
private readonly RequestDelegate next;
private CacheClientDB _cacheClientDB;
public OcelotMiddleware(RequestDelegate next, CacheClientDB cacheClientDB)
private CacheInvoker _cacheClientDB;
public OcelotMiddleware(RequestDelegate next, CacheInvoker cacheClientDB)
{
this.next = next;
this._cacheClientDB = cacheClientDB;

View File

@@ -35,7 +35,7 @@ namespace Yi.Framework.Core
//这里可以优化一下
//根据缓存获取全部用户信息
var userRoleMenu = ServiceLocator.Instance.GetService<CacheClientDB>().Get<UserRoleMenuDto>("用户id");
var userRoleMenu = ServiceLocator.Instance.GetService<CacheInvoker>().Get<UserRoleMenuDto>("用户id");
var roles = userRoleMenu.Roles;

View File

@@ -18,7 +18,7 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
if (Appsettings.appBool("Redis_Enabled"))
{
services.Configure<RedisConnOptions>(Appsettings.appConfiguration("RedisConnOptions"));
services.AddSingleton<CacheClientDB>();
services.AddSingleton<CacheInvoker>();
}
return services;
}

View File

@@ -20,7 +20,7 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
if (Appsettings.appBool("RedisSeed_Enabled"))
{
var _cacheClientDB = app.ApplicationServices.GetService<CacheClientDB>();
var _cacheClientDB = app.ApplicationServices.GetService<CacheInvoker>();
try
{

View File

@@ -3,7 +3,7 @@
round
:width="width"
:height="height"
:src="url+(src??'0')"
:src="url+(src??'0')+'/true'"
/>
</template>

View File

@@ -36,7 +36,7 @@
fit="cover"
width="100%"
height="7rem"
:src="url + image"
:src="url + image+'/true'"
radius="5"
/>
<template v-slot:loading>