网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using AutoMapper;

namespace Dpz.Core.WebApi.Controllers;

/// <summary>
/// 书签
/// </summary>
[ApiController, Route("api/[controller]")]
public class BookmarkController(
    IBookmarkService bookmarkService,
    IHttpClientFactory httpClientFactory,
    IObjectStorageOperation objectStorageService,
    IConfiguration configuration,
    ILogger<BookmarkController> logger
) : ControllerBase
{
    private readonly IMapper _mapper = CreateMapper();

    [NonAction]
    private static IMapper CreateMapper()
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<CreateBookmarkDto, VmCreateBookmark>();
            cfg.CreateMap<UpdateBookmarkDto, VmUpdateBookmark>();
        });
        return config.CreateMapper();
    }

    /// <summary>
    /// 获取书签
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="categories">分类</param>
    /// <returns></returns>
    [HttpGet]
    [ProducesResponseType<List<VmBookmark>>(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetBookmarks(
        [FromQuery] string title = "",
        [FromQuery] string[] categories = null
    )
    {
        var list = await bookmarkService.GetBookmarksAsync(title, categories);
        return Ok(list);
    }

    /// <summary>
    /// 获取所有分类
    /// </summary>
    /// <returns></returns>
    [HttpGet("categories")]
    [ProducesResponseType<List<string>>(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetAllCategories()
    {
        var list = await bookmarkService.GetCategoriesAsync();
        return Ok(list);
    }

    /// <summary>
    /// 搜索书签
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="categories">分类</param>
    /// <returns></returns>
    [HttpGet("search")]
    [ProducesResponseType<List<string>>(StatusCodes.Status200OK)]
    public async Task<IActionResult> Search(
        [FromQuery] string title = "",
        [FromQuery] string[] categories = null
    )
    {
        var list = await bookmarkService.SearchAsync(title, categories);
        return Ok(list);
    }

    /// <summary>
    /// 书签详情
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    [ProducesResponseType<VmBookmark>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetBookmark(string id)
    {
        var bookmark = await bookmarkService.GetBookmarkAsync(id);
        if (bookmark == null)
            return NotFound();
        return Ok(bookmark);
    }

    /// <summary>
    /// 新建书签
    /// </summary>
    /// <param name="bookmark"></param>
    /// <returns></returns>
    [HttpPost, Authorize(Policy = "System")]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    public async Task<IActionResult> CreateBookmark(CreateBookmarkDto bookmark)
    {
        var viewModel = _mapper.Map<VmCreateBookmark>(bookmark);
        viewModel.UploadIcon = UploadIconAsync;
        viewModel.UploadImage = UploadImageAsync;
        await bookmarkService.CreateBookmarkAsync(viewModel);
        return NoContent();
    }

    /// <summary>
    /// 删除书签
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}"), Authorize(Policy = ApiPermission.System)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    public async Task<IActionResult> Delete(string id)
    {
        await bookmarkService.DeleteAsync(
            id,
            async x =>
            {
                var host = configuration.GetSection("upyun")["Host"];
                if (string.IsNullOrEmpty(host))
                    return;
                if (
                    !string.IsNullOrEmpty(x.Icon)
                    && x.Icon.StartsWith(host, StringComparison.CurrentCultureIgnoreCase)
                )
                {
                    var pathToFile = x.Icon[host.Length..];
                    await objectStorageService.DeleteAsync(pathToFile);
                }

                if (
                    !string.IsNullOrEmpty(x.Image)
                    && x.Image.StartsWith(host, StringComparison.CurrentCultureIgnoreCase)
                )
                {
                    var pathToFile = x.Image[host.Length..];
                    await objectStorageService.DeleteAsync(pathToFile);
                }
            }
        );
        return NoContent();
    }

    /// <summary>
    /// 更新标签
    /// </summary>
    /// <param name="bookmark"></param>
    /// <returns></returns>
    [HttpPut]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    public async Task<IActionResult> UpdateBookmark(UpdateBookmarkDto bookmark)
    {
        var viewModel = _mapper.Map<VmUpdateBookmark>(bookmark);
        viewModel.UploadIcon = UploadIconAsync;
        viewModel.UploadImage = UploadImageAsync;
        viewModel.DeleteIcon = DeleteUpyunAsync;
        viewModel.DeleteImage = DeleteUpyunAsync;
        await bookmarkService.UpdateAsync(viewModel);
        return NoContent();
    }

    [NonAction]
    async Task<string> UploadIconAsync(string url)
    {
        if (string.IsNullOrEmpty(url))
            return null;
        var uri = new Uri(url);
        var extensionName = Path.GetExtension(uri.AbsolutePath);
        var httpClient = httpClientFactory.CreateClient("edge");
        var request = new HttpRequestMessage(HttpMethod.Get, uri);
        try
        {
            var response = await httpClient.SendAsync(request);
            var stream = await response.Content.ReadAsStreamAsync();
            var result = await objectStorageService.UploadAsync(
                stream,
                new[] { "images", "bookmark", "icon" },
                $"{ObjectId.GenerateNewId()}{extensionName}"
            );
            return result.AccessUrl;
        }
        catch (Exception e)
        {
            logger.LogError(e, "download icon fail");
            return null;
        }
    }

    [NonAction]
    async Task<string> UploadImageAsync(string url)
    {
        if (string.IsNullOrEmpty(url))
            return null;
        var uri = new Uri(url);
        var extensionName = Path.GetExtension(uri.AbsolutePath);
        var httpClient = httpClientFactory.CreateClient("edge");
        var request = new HttpRequestMessage(HttpMethod.Get, uri);
        try
        {
            var response = await httpClient.SendAsync(request);
            var stream = await response.Content.ReadAsStreamAsync();
            var result = await objectStorageService.UploadAsync(
                stream,
                new[] { "images", "bookmark", "image" },
                $"{ObjectId.GenerateNewId()}{extensionName}"
            );
            return result.AccessUrl;
        }
        catch (Exception e)
        {
            logger.LogError(e, "download image fail");
            return null;
        }
    }

    [NonAction]
    async Task DeleteUpyunAsync(string url)
    {
        var host = configuration.GetSection("upyun")["Host"];
        if (
            !string.IsNullOrEmpty(url)
            && !string.IsNullOrEmpty(host)
            && url.StartsWith(host, StringComparison.CurrentCultureIgnoreCase)
        )
        {
            var pathToFile = url[host.Length..];
            await objectStorageService.DeleteAsync(pathToFile);
        }
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码是一个 ASP.NET Core Web API 控制器,名为 BookmarkController,用于管理书签(Bookmark)的相关操作。以下是代码的主要功能和结构的详细解释:

1. 控制器概述

  • 命名空间: Dpz.Core.WebApi.Controllers
  • 特性:
    • [ApiController]:指示该类是一个 API 控制器,启用一些 API 特性(如自动模型验证)。
    • [Route("api/[controller]")]:定义路由模板,允许通过 api/bookmark 访问该控制器。

2. 构造函数

控制器的构造函数接受多个依赖项:

  • IBookmarkService bookmarkService:用于处理书签相关的业务逻辑。
  • IHttpClientFactory httpClientFactory:用于创建 HTTP 客户端实例。
  • IObjectStorageOperation objectStorageService:用于处理对象存储操作(如上传和删除文件)。
  • IConfiguration configuration:用于访问应用程序的配置设置。
  • ILogger<BookmarkController> logger:用于记录日志。

3. AutoMapper 配置

  • 使用 AutoMapper 将数据传输对象(DTO)映射到视图模型(ViewModel)。
  • CreateMapper 方法定义了两个映射规则:
    • CreateBookmarkDtoVmCreateBookmark
    • UpdateBookmarkDtoVmUpdateBookmark

4. API 方法

控制器包含多个 API 方法,处理不同的书签相关请求:

4.1 获取书签

  • 方法: GetBookmarks
  • HTTP 方法: GET
  • 功能: 根据标题和分类获取书签列表。

4.2 获取所有分类

  • 方法: GetAllCategories
  • HTTP 方法: GET
  • 功能: 获取所有书签分类。

4.3 搜索书签

  • 方法: Search
  • HTTP 方法: GET
  • 功能: 根据标题和分类搜索书签。

4.4 获取书签详情

  • 方法: GetBookmark
  • HTTP 方法: GET
  • 功能: 根据书签 ID 获取书签的详细信息。

4.5 新建书签

  • 方法: CreateBookmark
  • HTTP 方法: POST
  • 功能: 创建新的书签。需要授权(Authorize(Policy = "System"))。

4.6 删除书签

  • 方法: Delete
  • HTTP 方法: DELETE
  • 功能: 根据书签 ID 删除书签。需要授权。

4.7 更新书签

  • 方法: UpdateBookmark
  • HTTP 方法: PUT
  • 功能: 更新书签信息。

5. 辅助方法

控制器还包含一些辅助方法,用于处理图标和图片的上传和删除:

  • UploadIconAsync:上传书签图标。
  • UploadImageAsync:上传书签图片。
  • DeleteUpyunAsync:删除存储在 Upyun 的文件。

6. 错误处理

在上传图标和图片的过程中,使用 try-catch 块捕获异常,并记录错误日志。

总结

这个控制器提供了一个完整的 API 接口,用于管理书签的创建、读取、更新和删除(CRUD)操作,同时支持图标和图片的上传和删除。通过使用依赖注入和 AutoMapper,代码结构清晰,易于维护和扩展。

loading