C# Сохранение нескольких файлов на сервере в потоковой передаче
Подскажите как я могу сделать чтобы в рамках одного запроса через httpclient я мог передать составной запрос из нескольких файлов в потоке. Сейчас я могу передать в потоке один файл и сохранить его на сервере.
Код для отправки файла со стороны клиента
public async Task SendFile(string filePath, string url)
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
// Создаем объект MultipartFormDataContent для передачи файла
using (MultipartFormDataContent content = new MultipartFormDataContent())
{
// Создаем объект StreamContent для передачи содержимого файла
using (StreamContent fileContent = new StreamContent(fileStream))
{
client.DefaultRequestHeaders.Add("Token", "1234");
content.Add(fileContent, "file", System.IO.Path.GetFileName(filePath));
// Отправляем запрос на сервер с помощью метода HTTP POST
HttpResponseMessage response = await client.PostAsync(url, content);
// Получаем ответ от сервера и проверяем его статусный код
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Файл успешно передан.");
}
else
{
Console.WriteLine("Произошла ошибка при передаче файла.");
}
}
}
}
}
}
Код для сохранения файла с потока
[HttpPost("/uploadfile")]
//[DisableRequestSizeLimit]
[RequestSizeLimit((long)1e+10)]
[RequestFormLimits(MultipartBodyLengthLimit = (long)1e+10)]
public async Task<IActionResult> UploadFile()
{
if (!Request.HasFormContentType || !MediaTypeHeaderValue.TryParse(Request.ContentType, out var mediaTypeHeader) || string.IsNullOrEmpty(mediaTypeHeader.MediaType))
return new UnsupportedMediaTypeResult();
Stopwatch stopwatch = Stopwatch.StartNew();
using var fileStream = new FileStream("test.rar", FileMode.Create);
var buffer = new byte[1024 * 50];
int bytesRead;
while ((bytesRead = await Request.Body.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
}
stopwatch.Stop();
Console.WriteLine($"Время работы сохранения файла: {stopwatch.ElapsedMilliseconds}");
return Ok();
}
Ответы (1 шт):
Автор решения: xellan
→ Ссылка
Может кому пригодится, сохранение нескольких файлов в потоковой передаче, также можно чередавать с json запрос и т.п. Статья на данную тему https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-7.0
Код контролера
public class FileController : Controller
{
const long _RequestSizeLimit = (long)1e+10;
[HttpPost("/uploadfile")]
[RequestSizeLimit(_RequestSizeLimit)]
[RequestFormLimits(MultipartBodyLengthLimit = _RequestSizeLimit)]
public async Task<IActionResult> UploadPhysical()
{
if (!IsMultipartContentType(Request.ContentType))
return BadRequest("File\",\r\n\"The request couldn't be processed (Error 1).");
var boundary = GetBoundary(Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse(Request.ContentType));
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = System.Net.Http.Headers.ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
if (HasFileContentDisposition(contentDisposition))
await ProcessStreamedFile(section, contentDisposition);
if (HasJsonContentDisposition(contentDisposition, section))
{
var json = await section.ReadAsStringAsync();
var example = await JsonSerializer.DeserializeAsync<MyObject>(json);
}
}
section = await reader.ReadNextSectionAsync();
}
return Ok();
}
string GetBoundary(Microsoft.Net.Http.Headers.MediaTypeHeaderValue contentType) => HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;
bool IsMultipartContentType(string contentType) => !string.IsNullOrEmpty(contentType) && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
/// <summary>
/// Проверка на наличие файла в потоке
/// </summary>
/// <param name="contentDisposition"></param>
/// <returns></returns>
bool HasFileContentDisposition(System.Net.Http.Headers.ContentDispositionHeaderValue contentDisposition)
{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& (!string.IsNullOrEmpty(contentDisposition.FileName)
|| !string.IsNullOrEmpty(contentDisposition.FileNameStar));
}
/// <summary>
/// Проверка является на Json
/// </summary>
/// <param name="contentDisposition"></param>
/// <param name="section"></param>
/// <returns></returns>
bool HasJsonContentDisposition(System.Net.Http.Headers.ContentDispositionHeaderValue contentDisposition, MultipartSection section)
{
return contentDisposition != null && contentDisposition.DispositionType.Equals("form-data")
&& section.ContentType != null
&& section.ContentType.Contains("application/json");
}
/// <summary>
/// Запись файла с удалением запрещенных символов из пути, в contentDisposition.FileName могут присутствовать кавычки
/// </summary>
/// <param name="section"></param>
/// <param name="contentDisposition"></param>
/// <returns></returns>
async Task ProcessStreamedFile(MultipartSection section, System.Net.Http.Headers.ContentDispositionHeaderValue contentDisposition)
{
string fileName = contentDisposition.FileName;
string invalidChars = new string(Path.GetInvalidFileNameChars());
fileName = new string(fileName.Where(c => !invalidChars.Contains(c)).ToArray());
using (var memoryStream = new FileStream(fileName, FileMode.Create))
await section.Body.CopyToAsync(memoryStream, 1024 * 50);
}
}
Код для отправки данных на стороне клиента
public async Task SendFiles(List<string> filePaths, string url)
{
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
client.DefaultRequestHeaders.Add("Token", "1234");
// Создаем объект MultipartFormDataContent для передачи файлов
using (MultipartFormDataContent content = new MultipartFormDataContent())
{
var json = new StringContent("\"key\": \"Test\"", Encoding.UTF8, "application/json");
content.Add(json, "\"json\"");
foreach (var filePath in filePaths)
{
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var fileContent = new StreamContent(fileStream);
content.Add(fileContent, "files", System.IO.Path.GetFileName(filePath));
}
// Отправляем потоковый запрос на сервер с помощью метода HTTP POST
HttpResponseMessage response = await client.PostAsync(url, content);
// Получаем ответ от сервера и проверяем его статусный код
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"{filePaths.Count} files have been sent successfully.");
}
else
{
Console.WriteLine("An error occurred while sending files.");
}
}
}
}