Files
懒得勤快 a18c048f06 *
2024-08-10 23:03:33 +08:00

70 lines
2.3 KiB
C#

using Masuit.Tools.Core.AspNetCore;
using Masuit.Tools.Systems;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
namespace Masuit.Tools.AspNetCore.Extensions;
[ServiceInject(ServiceLifetime.Scoped)]
public class MultipartRequestService : IMultipartRequestService
{
public async Task<(Dictionary<string, StringValues>, byte[])> GetDataFromMultiPart(MultipartReader reader, CancellationToken cancellationToken)
{
var formAccumulator = new KeyValueAccumulator();
var file = Array.Empty<byte>();
while (await reader.ReadNextSectionAsync(cancellationToken) is { } section)
{
if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
{
continue;
}
if (contentDisposition.IsFormDisposition())
{
formAccumulator = await AccumulateForm(formAccumulator, section, contentDisposition);
}
else if (contentDisposition.IsFileDisposition())
{
await using var memoryStream = new PooledMemoryStream();
await section.Body.CopyToAsync(memoryStream, cancellationToken);
file = memoryStream.ToArray();
}
}
return (formAccumulator.GetResults(), file);
}
private Encoding GetEncoding(MultipartSection section)
{
var hasMediaTypeHeader = MediaTypeHeaderValue.TryParse(section.ContentType, out var mediaType);
if (!hasMediaTypeHeader || Encoding.UTF7.Equals(mediaType.Encoding))
{
return Encoding.UTF8;
}
return mediaType.Encoding;
}
private async Task<KeyValueAccumulator> AccumulateForm(KeyValueAccumulator formAccumulator, MultipartSection section, ContentDispositionHeaderValue contentDisposition)
{
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value;
using var streamReader = new StreamReader(section.Body, GetEncoding(section), true, 1024, true);
var value = await streamReader.ReadToEndAsync();
if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}
formAccumulator.Append(key, value);
if (formAccumulator.ValueCount > FormReader.DefaultValueCountLimit)
{
throw new InvalidDataException($"Form key count limit {FormReader.DefaultValueCountLimit} exceeded.");
}
return formAccumulator;
}
}