У меня есть серверная часть на ядре Asp.net, которая получает файл в Content-Type: заголовок формата multipart / form-data и отправляет его в хранилище Azure BLOB-объектов в потоке. Но когда я отправляю файл размером около 200 МБ и больше, у меня появляется ошибка
«Тело запроса слишком велико и превышает максимально допустимый предел»
, когда я искал, это могло произойти в старой версии WindowsAzure.Storage, но у меня есть версия 9.1.1. И как я посмотрел глубже, метод UploadFromStreamAsync по умолчанию использует чанк блоба на 4 МБ. Поэтому я не знаю, к чему только обратиться за помощью.
Мой контроллер:
public async Task<IActionResult> Post(string folder)
{
string azureBlobConnectionString = _configuration.GetConnectionString("BlobConnection");
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(azureBlobConnectionString);
HttpResponseUploadClass responseUploadClass = await Request.StreamFile(folder, storageAccount);
FormValueProvider formModel = responseUploadClass.FormValueProvider;
var viewModel = new MyViewModel();
var bindingSuccessful = await TryUpdateModelAsync(viewModel, prefix: "",
valueProvider: formModel);
if (!bindingSuccessful)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
}
return Ok(responseUploadClass.Url);
}
И класс, куда я отправляю поток файлового потока в лазурный блоб
public static async Task<HttpResponseUploadClass> StreamFile(this HttpRequest request, string folder, CloudStorageAccount blobAccount)
{
CloudBlobClient blobClient = blobAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(folder);
CloudBlockBlob blockBlob = null;
if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
{
throw new Exception($"Expected a multipart request, but got {request.ContentType}");
}
var formAccumulator = new KeyValueAccumulator();
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(request.ContentType),
DefaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
var disposition = ContentDispositionHeaderValue.Parse(section.ContentDisposition);
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
try
{
string fileName = HttpUtility.UrlEncode(disposition.FileName.Value.Replace("\"", ""), Encoding.UTF8);
blockBlob = container.GetBlockBlobReference(Guid.NewGuid().ToString());
blockBlob.Properties.ContentType = GetMimeTypeByWindowsRegistry(fileName);
blockBlob.Properties.ContentDisposition = "attachment; filename*=UTF-8''" + fileName;
await blockBlob.UploadFromStreamAsync(section.Body);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
{
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
var encoding = GetEncoding(section);
using (var streamReader = new StreamReader(
section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
var value = await streamReader.ReadToEndAsync();
if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
{
value = String.Empty;
}
formAccumulator.Append(key.Value, value);
if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
{
throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
}
}
}
}
section = await reader.ReadNextSectionAsync();
}
var formValueProvider = new FormValueProvider(
BindingSource.Form,
new FormCollection(formAccumulator.GetResults()),
CultureInfo.CurrentCulture);
return new HttpResponseUploadClass{FormValueProvider = formValueProvider, Url = blockBlob?.Uri.ToString()};
}