网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
namespace Dpz.Core.WebApi.Controllers;

/// <summary>
/// 图片管理
/// </summary>
[ApiController, Route("api/[controller]"), Authorize(Policy = "System")]
public class PictureController(
    IPictureRecordService pictureRecordService,
    IObjectStorageOperation objectStorageService,
    ILogger<PictureController> logger
) : ControllerBase
{
    /// <summary>
    /// 图片列表
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ProducesResponseType<List<VmPictureRecord>>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> GetPictures([FromQuery] PictureQueryParameterDto parameter)
    {
        var query = new VmPictureQuery
        {
            Tag = parameter.Tag,
            Description = parameter.Description,
            Type = parameter.Type
        };
        var list = await pictureRecordService.GetPagesAsync(
            [parameter.Tag],
            parameter.Description,
            parameter.PageIndex,
            parameter.PageSize
        );
        list.AddPaginationMetadata(Response.Headers);
        return Ok(list);
    }

    /// <summary>
    /// 上传图片
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> CreatePicture([FromForm] PictureCreateDto model)
    {
        if (model.Image.Length <= 0 || !model.Image.ContentType.Contains("image"))
        {
            return BadRequest("please select image to upload");
        }

        model.Tags = model
            .Tags?.Select(x => x?.Trim())
            .Where(x => !string.IsNullOrEmpty(x))
            .ToList();
        var userInfo = User.GetIdentity();

        using var memoryStream = new MemoryStream();
        await model.Image.CopyToAsync(memoryStream);
        var bytes = memoryStream.ToArray();

        var path = new[] { "images", "album", DateTime.Now.ToString("yyyy-MM") };
        var filename = $"{ObjectId.GenerateNewId()}.{await GetImageFormatAsync(bytes) ?? "jpg"}";
        var result = await objectStorageService.UploadAsync(
            model.Image.OpenReadStream(),
            path,
            filename
        );

        var pictureRecord = new VmPictureRecord
        {
            Creator = userInfo,
            UploadTime = DateTime.Now,
            Tags = model.Tags,
            Description = model.Description,
            Category = PictureCategory.Album,
            AccessUrl = result.AccessUrl,
            Length = bytes.Length,
            ObjectStorageUploadTime = DateTime.Now,
            Md5 = CalculateMd5(bytes),
            Width = result.Width,
            Height = result.Height,
        };
        await pictureRecordService.CreateRecordAsync(pictureRecord);

        return NoContent();
    }

    [NonAction]
    private static string CalculateMd5(byte[] bytes)
    {
        using var md5 = MD5.Create();
        var hash = md5.ComputeHash(bytes);
        return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
    }

    [NonAction]
    private async Task<string> GetImageFormatAsync(byte[] bytes)
    {
        try
        {
            using var stream = new MemoryStream(bytes);
            using var image = await Image.LoadAsync(stream);
            return image.Metadata.DecodedImageFormat?.FileExtensions.FirstOrDefault() ?? "jpg";
        }
        catch (Exception e)
        {
            logger.LogError(e, "get image format fail");
            return null;
        }
    }

    /// <summary>
    /// 修改图像、图像信息
    /// </summary>
    /// <returns></returns>
    [HttpPatch]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> EditPicture([FromBody] PictureEditDto model)
    {
        model.Tags = model
            .Tags?.Select(x => x?.Trim())
            .Where(x => !string.IsNullOrEmpty(x))
            .ToList();

        var recordChange = new VmPictureRecordChange
        {
            Category = PictureCategory.Album,
            Description = model.Description,
            Tags = model.Tags,
            Id = model.Id
        };

        await pictureRecordService.ChangeInformationAsync(recordChange);
        return NoContent();
    }

    /// <summary>
    /// 获取图片信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    [ProducesResponseType<VmPictureRecord>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetPicture(string id)
    {
        var picture = await pictureRecordService.GetPictureRecordAsync(id);
        if (picture == null)
            return NotFound();
        return Ok(picture);
    }

    /// <summary>
    /// 删除图像
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Delete(string id)
    {
        var pictureRecord = await pictureRecordService.GetPictureRecordAsync(id);
        if (pictureRecord == null)
            return NotFound();
        await pictureRecordService.DeleteAsync(id);
        await objectStorageService.DeleteAsync(pictureRecord.AccessUrl);
        return NoContent();
    }

    /// <summary>
    /// 获取所有标签
    /// </summary>
    /// <returns></returns>
    [HttpGet("tags")]
    [ProducesResponseType<List<string>>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> GetPictureTags()
    {
        var tags = await pictureRecordService.GetTagsAsync();
        return Ok(tags);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码是一个 ASP.NET Core Web API 控制器,名为 PictureController,用于管理图片的上传、查询、编辑和删除等操作。以下是对代码中各个部分功能的详细解释:

1. 控制器声明

[ApiController, Route("api/[controller]"), Authorize(Policy = "System")]
public class PictureController : ControllerBase
  • ApiController:标记该类为 API 控制器,启用一些特性,如自动模型验证。
  • Route("api/[controller]"):定义路由模板,[controller] 会被替换为控制器的名称(即 Picture)。
  • Authorize(Policy = "System"):要求用户必须通过授权策略 "System" 才能访问该控制器中的方法。

2. 构造函数

public PictureController(IPictureRecordService pictureRecordService, IObjectStorageOperation objectStorageService, ILogger<PictureController> logger)
  • 接受三个依赖项:
    • IPictureRecordService:用于处理图片记录的服务。
    • IObjectStorageOperation:用于处理对象存储操作的服务(如上传和删除图片)。
    • ILogger<PictureController>:用于记录日志。

3. 获取图片列表

[HttpGet]
public async Task<IActionResult> GetPictures([FromQuery] PictureQueryParameterDto parameter)
  • 处理 GET 请求,返回图片列表。
  • 接收查询参数 PictureQueryParameterDto,用于过滤图片。
  • 调用 pictureRecordService.GetPagesAsync 获取分页的图片记录,并返回结果。

4. 上传图片

[HttpPost]
public async Task<IActionResult> CreatePicture([FromForm] PictureCreateDto model)
  • 处理 POST 请求,上传图片。
  • 验证上传的文件是否为图片。
  • 生成唯一的文件名并上传到对象存储。
  • 创建图片记录并保存到数据库。

5. 计算 MD5 哈希

private static string CalculateMd5(byte[] bytes)
  • 计算给定字节数组的 MD5 哈希值,用于唯一标识图片内容。

6. 获取图片格式

private async Task<string> GetImageFormatAsync(byte[] bytes)
  • 通过加载图片流来获取图片格式,返回文件扩展名。

7. 编辑图片信息

[HttpPatch]
public async Task<IActionResult> EditPicture([FromBody] PictureEditDto model)
  • 处理 PATCH 请求,修改图片信息(如描述和标签)。
  • 调用 pictureRecordService.ChangeInformationAsync 更新记录。

8. 获取单个图片信息

[HttpGet("{id}")]
public async Task<IActionResult> GetPicture(string id)
  • 处理 GET 请求,获取指定 ID 的图片信息。
  • 如果找不到记录,返回 404 Not Found。

9. 删除图片

[HttpDelete("{id}")]
public async Task<IActionResult> Delete(string id)
  • 处理 DELETE 请求,删除指定 ID 的图片。
  • 在删除记录后,还会从对象存储中删除实际的图片文件。

10. 获取所有标签

[HttpGet("tags")]
public async Task<IActionResult> GetPictureTags()
  • 处理 GET 请求,返回所有图片标签的列表。

总结

这个控制器提供了一整套 RESTful API 接口,用于管理图片的生命周期,包括上传、查询、编辑、删除和获取标签等功能。通过依赖注入的方式,控制器能够与服务层进行交互,处理业务逻辑。

loading