网站首页 网站源码
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);
}
}
}
上述代码是一个 ASP.NET Core Web API 控制器,名为 BookmarkController
,用于管理书签(Bookmark)的相关操作。以下是代码的主要功能和结构的详细解释:
Dpz.Core.WebApi.Controllers
[ApiController]
:指示该类是一个 API 控制器,启用一些 API 特性(如自动模型验证)。[Route("api/[controller]")]
:定义路由模板,允许通过 api/bookmark
访问该控制器。控制器的构造函数接受多个依赖项:
IBookmarkService bookmarkService
:用于处理书签相关的业务逻辑。IHttpClientFactory httpClientFactory
:用于创建 HTTP 客户端实例。IObjectStorageOperation objectStorageService
:用于处理对象存储操作(如上传和删除文件)。IConfiguration configuration
:用于访问应用程序的配置设置。ILogger<BookmarkController> logger
:用于记录日志。AutoMapper
将数据传输对象(DTO)映射到视图模型(ViewModel)。CreateMapper
方法定义了两个映射规则:CreateBookmarkDto
到 VmCreateBookmark
UpdateBookmarkDto
到 VmUpdateBookmark
控制器包含多个 API 方法,处理不同的书签相关请求:
GetBookmarks
GetAllCategories
Search
GetBookmark
CreateBookmark
Authorize(Policy = "System")
)。Delete
UpdateBookmark
控制器还包含一些辅助方法,用于处理图标和图片的上传和删除:
UploadIconAsync
:上传书签图标。UploadImageAsync
:上传书签图片。DeleteUpyunAsync
:删除存储在 Upyun 的文件。在上传图标和图片的过程中,使用 try-catch
块捕获异常,并记录错误日志。
这个控制器提供了一个完整的 API 接口,用于管理书签的创建、读取、更新和删除(CRUD)操作,同时支持图标和图片的上传和删除。通过使用依赖注入和 AutoMapper,代码结构清晰,易于维护和扩展。