广东网站建设公司排名,网页设计模板网站免费,岚山区建设局网站,电商网站建设与管理实践1. 功能效果演示 仓库地址#xff1a;IcoTool[1]在线演示地址#xff1a;https://tool.dotnet9.com/ico[2]演示下文件上传、转换结果#xff1a;通过该工具及代码#xff0c;能了解到#xff1a;使用Blazor怎么上传文件到服务器(Blazor Server)。怎么从服务器下载文件。如… 1. 功能效果演示 仓库地址IcoTool[1]在线演示地址https://tool.dotnet9.com/ico[2]演示下文件上传、转换结果通过该工具及代码能了解到使用Blazor怎么上传文件到服务器(Blazor Server)。怎么从服务器下载文件。如何将png等图片转换为Ico图片。下面对该工具的实现代码做个简单说明不太清楚的可以留言交流。2. 实现说明 通过该工具能了解到使用Blazor怎么上传文件到服务器(Blazor Server)。怎么从服务器下载文件。如何将png等图片转换为Ico图片。下面对该工具的实现代码做个简单说明不太清楚的可以留言交流。2.1 其他图片上传使用的MASA Blazor[3]上传组件MFileInput[4]看下面的代码就一个上传组件加上传时文件保存操作代码文件IcoTool.razor[5]MFileInput TValueIBrowserFilePlaceholderT(IcoToolMFileInputPlaceholder)Rules_rulesShowSizeOnChangeLoadFileAcceptimage/png, image/jpeg, image/jpg, image/bmpLabelT(IcoToolMFileInputLabel)
/MFileInputcode {private bool _loading;private string _sourceFilePath ;[Inject] public I18n I18N { get; set; } default!;[Inject] public IJSRuntime Js { get; set; } default!;protected override async Task OnInitializedAsync(){_rules.Add(value (valuenull|| value.Size 2 * 1024 * 1024 )? true : T(IcoToolFileSizeLimitMessage));await base.OnInitializedAsync();}private async Task LoadFile(IBrowserFile? e){if (e null){_destFilePath _sourceFilePath string.Empty;return;}_destFilePath string.Empty;if (!string.IsNullOrWhiteSpace(_sourceFilePath) File.Exists(_sourceFilePath)) File.Delete(_sourceFilePath);var saveImageDir Path.Combine(AppDomain.CurrentDomain.BaseDirectory, wwwroot, ImageDirName);if (!Directory.Exists(saveImageDir)) Directory.CreateDirectory(saveImageDir);_sourceFilePath Path.Combine(saveImageDir, DateTime.UtcNow.ToString(yyyyMMddHHmmssfff));await using var fs new FileStream(_sourceFilePath, FileMode.Create);await e.OpenReadStream().CopyToAsync(fs);}
}2.2 核心代码其他图片转Ico参考代码https://gist.github.com/darkfall/1656050[6]因为使用到Bitmapvs会提示只支持Windows平台目前工具程序也部署在Windows Server 2019服务器上如果有其他转换代码支持跨平台欢迎技术讨论下面给出我使用的其他图片转Ico的代码代码路径在ImagingHelper.cs[7]using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;namespace Dotnet9.Tools.Images;/// summary
/// Adapted from this gist: https://gist.github.com/darkfall/1656050
/// Provides helper methods for imaging
/// /summary
public static class ImagingHelper
{public const string FileheadBmp 6677;public const string FileheadJpg 255216;public const string FileheadPng 13780;public const string FileheadGif 7173;private static readonly DictionaryImageType, string ImageTypeHead new(){{ ImageType.Bmp, FileheadBmp },{ ImageType.Jpg, FileheadJpg },{ ImageType.Png, FileheadPng },{ ImageType.Gif, FileheadGif }};public static bool IsPicture(string filePath, out string fileHead){fileHead string.Empty;try{var fs new FileStream(filePath, FileMode.Open, FileAccess.Read);var reader new BinaryReader(fs);var fileClass ${reader.ReadByte().ToString()}{reader.ReadByte().ToString()};reader.Close();fs.Close();if (fileClass is not (FileheadBmp or FileheadJpg or FileheadPng or FileheadGif))return false;fileHead fileClass;return true;}catch{return false;}}public static bool IsPictureType(string filePath, ImageType imageType){var isPicture IsPicture(filePath, out var fileHead);if (!isPicture) return false;return ImageTypeHead[imageType] fileHead;}/// summary/// Converts a PNG image to a icon (ico) with all the sizes windows likes/// /summary/// param nameinputBitmapThe input bitmap/param/// param nameoutputThe output stream/param/// returnsWether or not the icon was succesfully generated/returnspublic static bool ConvertToIcon(Bitmap inputBitmap, Stream output){var sizes new[] { 256, 48, 32, 16 };// Generate bitmaps for all the sizes and toss them in streamsvar imageStreams new ListMemoryStream();foreach (var size in sizes){var newBitmap ResizeImage(inputBitmap, size, size);var memoryStream new MemoryStream();newBitmap.Save(memoryStream, ImageFormat.Png);imageStreams.Add(memoryStream);}var iconWriter new BinaryWriter(output);var offset 0;// 0-1 reserved, 0iconWriter.Write((byte)0);iconWriter.Write((byte)0);// 2-3 image type, 1 icon, 2 cursoriconWriter.Write((short)1);// 4-5 number of imagesiconWriter.Write((short)sizes.Length);offset 6 16 * sizes.Length;for (var i 0; i sizes.Length; i){// image entry 1// 0 image widthiconWriter.Write((byte)sizes[i]);// 1 image heighticonWriter.Write((byte)sizes[i]);// 2 number of colorsiconWriter.Write((byte)0);// 3 reservediconWriter.Write((byte)0);// 4-5 color planesiconWriter.Write((short)0);// 6-7 bits per pixeliconWriter.Write((short)32);// 8-11 size of image dataiconWriter.Write((int)imageStreams[i].Length);// 12-15 offset of image dataiconWriter.Write(offset);offset (int)imageStreams[i].Length;}for (var i 0; i sizes.Length; i){// write image data// png data must contain the whole png data fileiconWriter.Write(imageStreams[i].ToArray());imageStreams[i].Close();}iconWriter.Flush();return true;}/// summary/// Converts a PNG image to a icon (ico)/// /summary/// param nameinputThe input stream/param/// param nameoutputThe output stream/param/// returnsWether or not the icon was succesfully generated/returnspublic static bool ConvertToIcon(Stream input, Stream output){var inputBitmap (Bitmap)Image.FromStream(input);return ConvertToIcon(inputBitmap, output);}/// summary/// Converts a PNG image to a icon (ico)/// /summary/// param nameinputPathThe input path/param/// param nameoutputPathThe output path/param/// returnsWether or not the icon was succesfully generated/returnspublic static bool ConvertToIcon(string inputPath, string outputPath){using var inputStream new FileStream(inputPath, FileMode.Open);using var outputStream new FileStream(outputPath, FileMode.OpenOrCreate);return ConvertToIcon(inputStream, outputStream);}/// summary/// Converts an image to a icon (ico)/// /summary/// param nameinputImageThe input image/param/// param nameoutputPathThe output path/param/// returnsWether or not the icon was succesfully generated/returnspublic static bool ConvertToIcon(Image inputImage, string outputPath){using var outputStream new FileStream(outputPath, FileMode.OpenOrCreate);return ConvertToIcon(new Bitmap(inputImage), outputStream);}/// summary/// Resize the image to the specified width and height./// Found on stackoverflow: https://stackoverflow.com/questions/1922040/resize-an-image-c-sharp/// /summary/// param nameimageThe image to resize./param/// param namewidthThe width to resize to./param/// param nameheightThe height to resize to./param/// returnsThe resized image./returnspublic static Bitmap ResizeImage(Image image, int width, int height){var destRect new Rectangle(0, 0, width, height);var destImage new Bitmap(width, height);destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);using var graphics Graphics.FromImage(destImage);graphics.CompositingMode CompositingMode.SourceCopy;graphics.CompositingQuality CompositingQuality.HighQuality;graphics.InterpolationMode InterpolationMode.HighQualityBicubic;graphics.SmoothingMode SmoothingMode.HighQuality;graphics.PixelOffsetMode PixelOffsetMode.HighQuality;using var wrapMode new ImageAttributes();wrapMode.SetWrapMode(WrapMode.TileFlipXY);graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);return destImage;}
}public enum ImageType
{Bmp,Jpg,Png,Gif
}简单的单元测试还是要有的代码见ImageHelperTests.cs[8]using Dotnet9.Tools.Images;namespace Dotnet9.Tools.Tests.Images;public class ImageHelperTests
{[Fact]public void IsPicture(){var testFilePath Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TestFiles, logo.png);Assert.True(File.Exists(testFilePath));var isPicture ImagingHelper.IsPicture(testFilePath, out var typename);Assert.True(isPicture);}[Fact]public void IsNotPicture(){var testFilePath Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TestFiles, test.txt);Assert.True(File.Exists(testFilePath));var isPicture ImagingHelper.IsPicture(testFilePath, out var typename);Assert.False(isPicture);}[Fact]public void IsPngFile(){var testFilePath Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TestFiles, logo.png);Assert.True(File.Exists(testFilePath));var isPng ImagingHelper.IsPictureType(testFilePath, ImageType.Png);Assert.True(isPng);}[Fact]public void ShouldConvertPngToIcon(){var sourcePng Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TestFiles, logo.png);var destIco Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TestFiles, logo.ico);Assert.True(File.Exists(sourcePng));Assert.False(File.Exists(destIco));ImagingHelper.ConvertToIcon(sourcePng, destIco);Assert.True(File.Exists(destIco));File.Delete(destIco);}
}页面调用Ico转换功能代码如下提供一个触发转换的按钮和执行转换的方法代码文件IcoTool.razor[9]if (!string.IsNullOrWhiteSpace(_sourceFilePath) File.Exists(_sourceFilePath))
{MButton classma-2 white--textLoading_loadingDisabled_loadingDepressed ColorprimaryOnClickConvertToIconLoaderContentspanT(IcoToolMButtonLoaderContent)/span/LoaderContentChildContentspanT(IcoToolMButtonChildContent)/span/ChildContent/MButton
}code {private async Task ConvertToIcon(){if (!string.IsNullOrWhiteSpace(_destFilePath) File.Exists(_destFilePath)){await DownloadIco();return;}_loading true;if (!string.IsNullOrWhiteSpace(_sourceFilePath) File.Exists(_sourceFilePath)){_destFilePath ${_sourceFilePath}.ico;if (ImagingHelper.ConvertToIcon(_sourceFilePath, _destFilePath)) await DownloadIco();}_loading false;}
}2.3 转换后的Ico文件下载 文件转换成功后怎么提供下载呢起初想使用一个a href/files/xxx.ico target_blankxxx.ico/a标签提供浏览下载的但动态生成的图片无法访问不知道什么原因只能暂时采用一个折衷的方式有朋友有好的想法欢迎留言。目前采用的是提供按钮下载下面是封装的js下载方法来自微软的文档ASP.NET Core Blazor file downloads[10]我把JS代码放_Layout.cshtml[11]script// 省略部分代码async function downloadFileFromStream(fileName, contentStreamReference) {const arrayBuffer await contentStreamReference.arrayBuffer();const blob new Blob([arrayBuffer]);const url URL.createObjectURL(blob);triggerFileDownload(fileName, url);URL.revokeObjectURL(url);}function triggerFileDownload(fileName, url) {const anchorElement document.createElement(a);anchorElement.href url;if (fileName) {anchorElement.download fileName;}anchorElement.click();anchorElement.remove();}
/script页面下载时使用以下代码使用到JS互操作(什么是JS互操作可以参考我转载的这篇文章了解首页.NETBlazorBlazor Server (14/30)大家一起学BlazorJavaScript interop(互操作))代码放IcoTool.razor[12]inject IJSRuntime JS// 省略n多代码code {private async Task DownloadIco(){await using var fileStream new FileStream(_destFilePath, FileMode.Open);using var streamRef new DotNetStreamReference(fileStream);await Js.InvokeVoidAsync(downloadFileFromStream, Path.GetFileName(_destFilePath), streamRef);}
}3. 总结 Blazor组件库使用的MASA Blazor[13]很美观大方的Material Design设计风格。Ico转换使用到了System.Drawing.Common包的Bitmap.NET 6开始不支持跨平台提示只支持Windows平台。本工具使用7.0.100-preview.1[14]开发、编译、上线使用.NET 6[15]的同学请放心使用可以无缝升级。Dotnet9工具箱会不断添加新的免费、开源、在线工具欢迎star支持有什么需求我会考虑加上仓库地址Dotnet9.Tools[16]可提交issue[17]、网站留言[18]、微信公众号(dotnet9)联系等等。本工具源码IcoTool[19]介绍文章Blazor在线Ico转换工具[20]在线演示地址https://tool.dotnet9.com/ico[21]参考资料[1]IcoTool: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor[2]https://tool.dotnet9.com/ico: https://tool.dotnet9.com/ico[3]MASA Blazor: https://masa-blazor-docs-dev.lonsid.cn/[4]MFileInput: https://masa-blazor-docs-dev.lonsid.cn/components/file-inputs[5]IcoTool.razor: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor[6]https://gist.github.com/darkfall/1656050: https://gist.github.com/darkfall/1656050[7]ImagingHelper.cs: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools/Images/ImagingHelper.cs[8]ImageHelperTests.cs: https://github.com/dotnet9/dotnet9.com/blob/develop/src/test/Dotnet9.Tools.Tests/Images/ImageHelperTests.cs[9]IcoTool.razor: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor[10]ASP.NET Core Blazor file downloads: https://docs.microsoft.com/en-us/aspnet/core/blazor/file-downloads?viewaspnetcore-6.0[11]_Layout.cshtml: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/_Layout.cshtml[12]IcoTool.razor: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor[13]MASA Blazor: https://masa-blazor-docs-dev.lonsid.cn/[14]7.0.100-preview.1: https://dotnet.microsoft.com/en-us/download/dotnet/7.0[15].NET 6: https://dotnet.microsoft.com/en-us/download/dotnet/6.0[16]Dotnet9.Tools: https://github.com/dotnet9/dotnet9.com[17]提交issue: https://github.com/dotnet9/dotnet9.com/issues/new[18]网站留言: https://dotnet9.com[19]IcoTool: https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor[20]Blazor在线Ico转换工具: https://dotnet9.com/?p1715在新窗口中打开[21]https://tool.dotnet9.com/ico: https://tool.dotnet9.com/ico