using MicrosoftAspNetCoreMvc;using NPOISSUserModel;using NPOIXSSFUserModel;using SystemReflection;using SystemTextJson;using SystemTextJsonNodes;WebApplicationBuilder builder = WebApplicationCreateBui
这段代码是一个使用AspNetCore构建的WebAPI应用程序,用于接收POST请求并生成并导出资产标签。以下是对代码的优化建议:
- 使用属性初始化器进行对象初始化:在AssetTag类中,可以使用属性初始化器来初始化属性值,而无需单独设置每个属性的值。
internal class AssetTag
{
public string? Company { get; set; }
public string? Id { get; set; }
public string? Name { get; set; }
public string? Model { get; set; }
public string? Attribute { get; set; }
public string? ArrivalDate { get; set; }
public string? ManagementLevel { get; set; }
}
- 使用System.Text.Json进行JSON反序列化:在MapPost方法中,可以使用System.Text.Json来反序列化请求体中的JSON数据,而无需使用JsonNodes库。
app.MapPost("/print", ([FromBody] JsonElement requestBody, ILogger<Program> logger) =>
{
string type = requestBody.GetProperty("type").GetString();
List<AssetTag> assetTagList = JsonSerializer.Deserialize<List<AssetTag>>(requestBody.GetProperty("assets").GetRawText());
// ...
});
- 使用using语句简化代码:在生成Excel文件的代码块和FileStream的代码块中,可以使用using语句来自动释放资源,而无需手动关闭流。
using (XSSFWorkbook workbook = new())
{
// ...
}
using FileStream fileStream = File.Open($@"{rootPath}\template\data.xlsx", FileMode.Create, FileAccess.Write);
workbook.Write(fileStream);
- 使用Path.Combine方法来拼接文件路径:在生成文件路径时,可以使用Path.Combine方法来拼接路径,而无需手动拼接字符串。
string rootPath = Path.Combine(app.Environment.WebRootPath, "file");
string assetTagFilePath = Path.Combine(rootPath, "export", $"asset-tag-{type}.pdf");
string exportFilePath = Path.Combine(rootPath, "export", $"{guid}.pdf");
string templateDataFilePath = Path.Combine(rootPath, "template", "data.xlsx");
string templateAssetTagFilePath = Path.Combine(rootPath, "template", $"asset-tag-{type}.btw");
- 使用Task.Delay方法替代Thread.Sleep方法:在延迟删除导出文件的代码块中,可以使用Task.Delay方法来替代Thread.Sleep方法,以避免阻塞线程。
await Task.Delay(TimeSpan.FromMinutes(2));
- 使用IHostedService实现定时删除文件:可以将文件删除逻辑封装到一个实现了IHostedService接口的后台服务中,以便在应用程序启动时启动该服务,并定期删除过期的导出文件。
优化后的代码如下所示:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddCors(options =>
options.AddDefaultPolicy(
builder => builder
.WithOrigins("*")
.AllowAnyHeader()
.AllowAnyMethod()
)
)
.AddHostedService<ExportFileCleanupService>()
.AddQueuePolicy(options =>
{
options.MaxConcurrentRequests = 1;
options.RequestQueueLimit = 5;
});
var app = builder.Build();
app.UseCors();
app.UseConcurrencyLimiter();
app.MapPost("/print", ([FromBody] JsonElement requestBody, ILogger<Program> logger) =>
{
string type = requestBody.GetProperty("type").GetString();
List<AssetTag> assetTagList = JsonSerializer.Deserialize<List<AssetTag>>(requestBody.GetProperty("assets").GetRawText())!;
string rootPath = Path.Combine(app.Environment.WebRootPath, "file");
string guid = Guid.NewGuid().ToString();
logger.LogInformation("[{Guid}]开始运行资产标签打印服务,正在导入数据...", guid);
PropertyInfo[] propertyInfos = typeof(AssetTag).GetProperties();
using var workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Sheet1");
for (int i = 0, length = assetTagList.Count + 1; i < length; i++)
{
IRow row = sheet.CreateRow(i);
for (int j = 0; j < propertyInfos.Length; j++)
{
if (i == 0)
{
row.CreateCell(j).SetCellValue(propertyInfos[j].Name);
}
else
{
row.CreateCell(j).SetCellValue((string)propertyInfos[j].GetValue(assetTagList[i - 1], null)!);
}
}
}
using FileStream fileStream = File.Open(templateDataFilePath, FileMode.Create, FileAccess.Write);
workbook.Write(fileStream);
logger.LogInformation("[{Guid}]数据已导入EXCEL,正在启动BarTender打印...", guid);
using var application = new BarTender.Application();
BarTender.Format format = application.Formats.Open(templateAssetTagFilePath);
format.Printer = "Foxit PDF Reader Printer";
format.PrintOut(false, false);
format.Close(BarTender.BtSaveOptions.btDoNotSaveChanges);
application.Quit(BarTender.BtSaveOptions.btDoNotSaveChanges);
GC.Collect();
File.Copy(assetTagFilePath, exportFilePath);
logger.LogInformation("[{Guid}]打印成功,已生成导出文件(文件保留2分钟)", guid);
Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromMinutes(2));
File.Delete(exportFilePath);
logger.LogInformation("[{Guid}]已删除导出文件", guid);
});
return Results.Ok(guid);
});
app.MapGet("/preview/{id}", ([FromRoute] string id) =>
{
string path = Path.Combine(app.Environment.WebRootPath, "file", "export", $"{id}.pdf");
if (!File.Exists(path))
{
return Results.NotFound("文件不存在");
}
return Results.File(path, "application/pdf");
});
app.Run();
internal class AssetTag
{
public string? Company { get; set; }
public string? Id { get; set; }
public string? Name { get; set; }
public string? Model { get; set; }
public string? Attribute { get; set; }
public string? ArrivalDate { get; set; }
public string? ManagementLevel { get; set; }
}
internal class ExportFileCleanupService : IHostedService
{
private readonly string exportFolderPath;
private readonly ILogger<ExportFileCleanupService> logger;
private readonly TimeSpan cleanupInterval = TimeSpan.FromMinutes(2);
private Timer cleanupTimer;
public ExportFileCleanupService(IWebHostEnvironment environment, ILogger<ExportFileCleanupService> logger)
{
this.exportFolderPath = Path.Combine(environment.WebRootPath, "file", "export");
this.logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
cleanupTimer = new Timer(DeleteExpiredExportFiles, null, TimeSpan.Zero, cleanupInterval);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
cleanupTimer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
private void DeleteExpiredExportFiles(object state)
{
try
{
DirectoryInfo directory = new DirectoryInfo(exportFolderPath);
foreach (FileInfo file in directory.GetFiles("*.pdf"))
{
if (DateTime.Now - file.CreationTime > cleanupInterval)
{
file.Delete();
logger.LogInformation("已删除导出文件: {FilePath}", file.FullName);
}
}
}
catch (Exception ex)
{
logger.LogError(ex, "删除导出文件时发生错误");
}
}
}
通过上述优化,代码更加简洁,并且使用了一些最佳实践,如属性初始化器、using语句、Path.Combine方法、Task.Delay方法和IHostedService接口。此外,添加了一个定时删除过期导出文件的后台服务,以保持文件目录的清洁
原文地址: https://www.cveoy.top/t/topic/hPZ3 著作权归作者所有。请勿转载和采集!