147 lines
5.3 KiB
C#
147 lines
5.3 KiB
C#
namespace SimpleAdmin.Web.Core;
|
|
|
|
/// <summary>
|
|
/// 提供员工端资料提交相关 HTTP 接口。
|
|
/// </summary>
|
|
[ApiDescriptionSettings("Application", Tag = "员工入职提交")]
|
|
[Route("open/onboarding")]
|
|
[AllowAnonymous]
|
|
public class OnboardingPublicSubmissionController
|
|
{
|
|
private readonly IOnboardingPublicSubmissionService _service;
|
|
private readonly IFileService _fileService;
|
|
|
|
public OnboardingPublicSubmissionController(IOnboardingPublicSubmissionService service, IFileService fileService)
|
|
{
|
|
_service = service;
|
|
_fileService = fileService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除当前入职任务中的一条已上传材料。
|
|
/// </summary>
|
|
[HttpPost("delete-material")]
|
|
public async Task DeleteMaterial(
|
|
[FromBody] OnboardingDeleteMaterialInput input)
|
|
{
|
|
await _service.DeleteMaterial(input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 确认已阅读指定合同。
|
|
/// </summary>
|
|
[HttpPost("confirm-contract")]
|
|
public async Task ConfirmContract([FromBody] OnboardingConfirmContractInput input)
|
|
{
|
|
await _service.ConfirmContract(input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提交入职资料进入审核。
|
|
/// </summary>
|
|
[HttpPost("submit")]
|
|
public async Task Submit([FromBody] OnboardingSubmitInput input)
|
|
{
|
|
await _service.Submit(input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 校验并上传员工入职材料。
|
|
/// </summary>
|
|
[HttpPost("upload-material")]
|
|
[Consumes("multipart/form-data")]
|
|
[RequestSizeLimit(21 * 1024 * 1024)]
|
|
public async Task UploadMaterial(
|
|
[FromQuery] string token,
|
|
[FromQuery] long materialTypeId,
|
|
[FromQuery] long? taskMaterialId,
|
|
[FromForm] IFormFile file)
|
|
{
|
|
if (file == null || file.Length == 0)
|
|
{
|
|
throw Oops.Bah("请选择需要上传的文件");
|
|
}
|
|
|
|
await _service.ValidateMaterialUpload(new OnboardingMaterialUploadValidationInput
|
|
{
|
|
Token = token,
|
|
MaterialTypeId = materialTypeId,
|
|
FileName = file.FileName,
|
|
FileLength = file.Length,
|
|
TaskMaterialId = taskMaterialId
|
|
});
|
|
await ValidateMaterialFileContent(file);
|
|
|
|
var fileId = await _fileService.UploadFile(SysDictConst.FILE_ENGINE_ALIYUN_OSS, file);
|
|
await _service.SaveMaterial(new OnboardingSaveMaterialInput
|
|
{
|
|
Token = token,
|
|
MaterialTypeId = materialTypeId,
|
|
FileId = fileId,
|
|
TaskMaterialId = taskMaterialId
|
|
});
|
|
}
|
|
|
|
private static async Task ValidateMaterialFileContent(IFormFile file)
|
|
{
|
|
var suffix = global::System.IO.Path.GetExtension(file.FileName).TrimStart('.').ToLowerInvariant();
|
|
var supported = suffix is "png" or "jpg" or "jpeg" or "gif" or "bmp" or "webp" or "pdf";
|
|
if (!supported)
|
|
throw Oops.Bah("仅允许上传图片或PDF文件");
|
|
|
|
var header = new byte[12];
|
|
var bytesRead = 0;
|
|
await using (var stream = file.OpenReadStream())
|
|
{
|
|
while (bytesRead < header.Length)
|
|
{
|
|
var read = await stream.ReadAsync(header.AsMemory(bytesRead, header.Length - bytesRead));
|
|
if (read == 0) break;
|
|
bytesRead += read;
|
|
}
|
|
}
|
|
|
|
var contentMatchesSuffix = suffix switch
|
|
{
|
|
"jpg" or "jpeg" => bytesRead >= 3 && header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF,
|
|
"png" => bytesRead >= 8
|
|
&& header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47
|
|
&& header[4] == 0x0D && header[5] == 0x0A && header[6] == 0x1A && header[7] == 0x0A,
|
|
"gif" => bytesRead >= 6
|
|
&& header[0] == 0x47 && header[1] == 0x49 && header[2] == 0x46
|
|
&& header[3] == 0x38 && (header[4] == 0x37 || header[4] == 0x39) && header[5] == 0x61,
|
|
"bmp" => bytesRead >= 2 && header[0] == 0x42 && header[1] == 0x4D,
|
|
"webp" => bytesRead >= 12
|
|
&& header[0] == 0x52 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x46
|
|
&& header[8] == 0x57 && header[9] == 0x45 && header[10] == 0x42 && header[11] == 0x50,
|
|
"pdf" => bytesRead >= 5
|
|
&& header[0] == 0x25 && header[1] == 0x50 && header[2] == 0x44
|
|
&& header[3] == 0x46 && header[4] == 0x2D,
|
|
_ => false
|
|
};
|
|
if (!contentMatchesSuffix)
|
|
throw Oops.Bah("文件真实格式与扩展名不一致,请上传有效的图片或PDF文件");
|
|
|
|
if (suffix == "pdf") return;
|
|
|
|
await using var imageStream = file.OpenReadStream();
|
|
SkiaSharp.SKCodec codec;
|
|
try
|
|
{
|
|
codec = SkiaSharp.SKCodec.Create(imageStream);
|
|
}
|
|
catch
|
|
{
|
|
throw Oops.Bah("图片文件已损坏或格式不受支持");
|
|
}
|
|
|
|
using (codec)
|
|
{
|
|
if (codec == null || codec.Info.Width <= 0 || codec.Info.Height <= 0)
|
|
throw Oops.Bah("图片文件已损坏或格式不受支持");
|
|
if ((long)codec.Info.Width * codec.Info.Height > 40_000_000L)
|
|
throw Oops.Bah("图片分辨率过大,请压缩后重新上传");
|
|
}
|
|
}
|
|
}
|