Вопрос или проблема
Я пишу программу на ASP.NET Core 6, которая получает много файлов и записывает их в базу данных SQLite.
Я использую следующий код на клиенте для отправки файла:
var request = new HttpRequestMessage()
{
Method = HttpMethod.Post,
RequestUri = new Uri(server.serverBase + "/api/snapshot/UploadFile"),
};
using (FileStream filestream = File.Open(file.getFilePath(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var length = filestream.Length.ToString();
var streamContent = new StreamContent(filestream, 16384);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
streamContent.Headers.Add("Content-Length", length);
request.Content = streamContent;
var httpClient = new HttpClient();
httpClient.Timeout = new TimeSpan(0, 2, 0);
var response = httpClient.SendAsync(request).Result;
//Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
А следующий код на сервере для получения потока:
[HttpPost("UploadFile")]
[RequestSizeLimit(100000000000)]
public async Task<IActionResult> UploadFile()
{
int CHUNK_SIZE = 1024 * 1024; //Размер кусочка 1 МБ
using (Stream stream = HttpContext.Request.Body)
{
var buffer = new byte[CHUNK_SIZE];
int bytesRead;
int chunkNumber = 0;
long totalNumBytes = 0;
int progress = 0;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
System.Diagnostics.Debug.WriteLine(bytesRead);
await ProcessChunk(buffer, bytesRead, chunkNumber, totalNumBytes);
chunkNumber++;
}
}
return Ok("Файл успешно загружен и разбит на кусочки.");
}
Тем не менее, несмотря на то, что размер буфера составляет 1048576 байт, вывод отладки всегда составляет 4096, т.е. я читаю только 4096 байт за каждый “кусочек” потока.
Как я могу увеличить размер буфера больше 4096 байт?
Моя конечная цель – взять каждый “кусочек” и сохранить его в базе данных как blob, большинство отправляемых файлов примерно 3KB, поэтому я планировал изменить размер каждого “кусочка” на 1KB, чтобы использовать меньше строк для каждого кусочка файла.
Я пробовал:
- Изменить лимиты Kestrel
- “enableBuffering” на объекте запроса
- Использовать
MemoryStream
Я ожидал, что буфер потока HttpContext.Request.Body
увеличится более чем на 4096 байт, но, похоже, я не могу превысить этот предел.
Вам стоит увеличить maxAllowedContentLength в вашем web.config
<configuration>
<system.webServer>
<security>
<requestFiltering removeServerHeader="true">
<requestLimits maxAllowedContentLength="2147483647" />
Ответ или решение
В вашем случае проблема с ограничением потока HttpContext.Request.Body
, который всегда равен 4096 байт, может быть связана с настройками Kestrel или IIS, а также с конфигурированием вашего ASP.NET Core приложения.
Чтобы решить вашу проблему, рассмотрим несколько важных моментов:
1. Увеличение ограничений на размер запроса в Kestrel
Убедитесь, что вы увеличили ограничения на размер запросов в конфигурации Kestrel. Эти параметры можно настроить в методе ConfigureServices
класса Startup
. Например:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = 104857600; // Устанавливаем 100MB
});
// Другие настройки сервисов
}
2. Настройка размера тела запроса для IIS
Если ваше приложение размещено в IIS, необходимо установить максимально допустимый размер тела запроса в web.config
. Убедитесь, что у вас есть следующая конфигурация:
<configuration>
<system.webServer>
<security>
<requestFiltering removeServerHeader="true">
<requestLimits maxAllowedContentLength="2147483647" /> <!-- 2GB в байтах -->
</requestFiltering>
</security>
</system.webServer>
</configuration>
3. Использование EnableBuffering
Хотя вы упомянули, что пробовали использовать EnableBuffering
, убедитесь, что вы вызываете его в вашем методе действия перед чтением потока:
[HttpPost("UploadFile")]
[RequestSizeLimit(100000000000)]
public async Task<IActionResult> UploadFile()
{
HttpContext.Request.EnableBuffering(); // Включаем буферизацию
int CHUNK_SIZE = 1024 * 1024; // 1 MB chunk size
using (Stream stream = HttpContext.Request.Body)
{
var buffer = new byte[CHUNK_SIZE];
int bytesRead;
int chunkNumber = 0;
long totalNumBytes = 0;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
// Обработка загруженного куска
await ProcessChunk(buffer, bytesRead, chunkNumber, totalNumBytes);
chunkNumber++;
}
}
return Ok("Файл загружен и chunked успешно.");
}
4. Некоторые дополнительные соображения
-
Асинхронность: Убедитесь, что вы не блокируете поток вашего приложения (например, с помощью
.Result
) при отправке запроса с клиента, так как это может привести к проблемам с производительностью или тайм-аутами. - Обработка ошибок: Не забудьте обрабатывать возможные исключения как на стороне клиента, так и на стороне сервера для лучшего контроля над ошибками.
Заключение
Проведя вышеперечисленные шаги, вы сможете увеличить лимиты потока и успешно обрабатывать загружаемые файлы. Убедитесь, что вы проверили все настройки, и зафиксируйте возможные проблемы, если пользователи все еще сталкиваются с ограничениями по размеру данных. Если у вас есть дополнительные вопросы, не стесняйтесь задавать их.