ASP.NET Core 给上传的图片加水印

2019-07-08 19:16:20 浏览数 (1)

图片加水印是网站中使用非常广泛的技术,可以保护网站内容的版权,例如我博客这样的网站。在传统ASP.NET(.NET Framework)中,我们可以使用System.Web.Helpers.WebImage来添加水印,就像这样:

代码语言:javascript复制
var image = new WebImage(imageBytes);
image.AddTextWatermark(
    Settings.Instance.WatermarkText, "White", Settings.Instance.WatermarkFontSize,
    opacity: Settings.Instance.WatermarkTextOpacityPercentage
    );

但是在.NET Core中,没有WebImage这个类型了。我们如何给图片加水印呢?

我们从图片上传开始。在ASP.NET Core中,我们用IFormFile来上传文件,也包括图片文件。需要详细了解可以参考微软官方文档:https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-2.1

在我的博客系统里,我写了一个Action用来上传图片,将图片文件塞到一个MemoryStream对象里,之后的图片存储服务就可以把它保存到目标位置

代码语言:javascript复制
[Route("image/upload")]
public async Task<IActionResult> UploadImageAsync(IFormFile file)
{
...
    using (var stream = new MemoryStream())
    {
        await file.CopyToAsync(stream);
        ... // call underlying image storage service
    }
...
}

要添加水印,我们需要修改图片stream。

但是.NET Core默认情况下没有处理图片的能力,因为System.Drawing命名空间里的API是非常有限的。我们需要引用一个微软官方的NuGet包来引入我们在.NET Framework中曾经熟悉的那些API:

Install-Package System.Drawing.Common -Version 4.5.1

现在我们就可以访问System.Drawing.ImageSystem.Drawing.Graphics等API了。

下面的代码将会使用这些类型在上传的图片的stream上添加文字水印:

代码语言:javascript复制
// Add watermark
var watermarkedStream = new MemoryStream();
using (var img = Image.FromStream(stream))
{
    using (var graphic = Graphics.FromImage(img))
    {
        var font = new Font(FontFamily.GenericSansSerif, 20, FontStyle.Bold, GraphicsUnit.Pixel);
        var color = Color.FromArgb(128, 255, 255, 255);
        var brush = new SolidBrush(color);
        var point = new Point(img.Width - 120, img.Height - 30);
        graphic.DrawString("edi.wang", font, brush, point);
        img.Save(watermarkedStream, ImageFormat.Png);
    }
}

结果就是这样的:

其中有一些要注意的地方:

1. 你不能更改原始stream,如果你尝试把图片存储覆盖原始stream的话,是不会有效果的,就像这样:

代码语言:javascript复制
img.Save(stream, ImageFormat.Png);

这就是为啥我定义了另一个watermarkedStream对象。

2. 针对水印的位置,也就是point对象。我的计算方式是添加水印到图片右下角,你需要根据自己需要修改这个位置。

3. 我建议字体采用跨平台的字体,因为.NET Core不止能部署在Windows上。

最后,我博客里上传图片加水印的完整样例代码如下:

代码语言:javascript复制
[Authorize]
[HttpPost]
[Route("image/upload")]
public async Task<IActionResult> UploadImageAsync(IFormFile file)
{
    try
    {
        if (null == file)
        {
            Logger.LogError("file is null.");
            return BadRequest();
        }
        if (file.Length > 0)
        {
            var name = Path.GetFileName(file.FileName);
            if (name != null)
            {
                using (var stream = new MemoryStream())
                {
                    await file.CopyToAsync(stream);
                    // Add watermark
                    var watermarkedStream = new MemoryStream();
                    using (var img = Image.FromStream(stream))
                    {
                        using (var graphic = Graphics.FromImage(img))
                        {
                            var font = new Font(FontFamily.GenericSansSerif, 20, FontStyle.Bold, GraphicsUnit.Pixel);
                            var color = Color.FromArgb(128, 255, 255, 255);
                            var brush = new SolidBrush(color);
                            var point = new Point(img.Width - 120, img.Height - 30);
                            graphic.DrawString("edi.wang", font, brush, point);
                            img.Save(watermarkedStream, ImageFormat.Png);
                        }
                    }
                    var response = await _imageStorageProvider.InsertAsync(name, watermarkedStream.ToArray());
                    Logger.LogInformation("Image Upload: "   JsonConvert.SerializeObject(response));
                    if (response.IsSuccess)
                    {
                        string refPath = "/uploads/"   response.Item;
                        return Json(new { location = refPath });
                    }
                    Logger.LogError(response.Message);
                    return StatusCode(StatusCodes.Status500InternalServerError);
                }
            }
        }
        return BadRequest();
    }
    catch (Exception e)
    {
        Logger.LogError(e, $"Error uploading image.");
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

0 人点赞