Конечная точка API загрузки файлов не работает после ASP. NET Перемещение ядра - PullRequest
0 голосов
/ 07 апреля 2020

Я только что перенес ASP. NET WebAPI в ASP. NET Core 2.1 (я также пробовал 2.2). Он содержит маршрут загрузки файла, который получает многокомпонентный запрос в двоичном файле с известным ключом / именем.

Моя проблема в том, что коллекция request.Form.Files пуста. Двоичный контент принимается как обычное значение формы (которое показывает только странные символы при разборе).

Насколько я понимаю, реализация клиентов неверна. Однако они являются мобильными приложениями, поэтому я должен поддерживать обратную совместимость. Это в основном то, как клиент отправляет файл:

var client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes("someimage.jpg")), "file");
await client.PutAsync("https://myapi/api/document", content);

Старая ASP. NET Реализация проанализировала его так (некоторые части удалены):

var provider = new MultipartMemoryStreamProvider();
await request.Content.ReadAsMultipartAsync(provider);

Stream file = null;
foreach (var contentPart in provider.Contents)
{
    if (partName.Equals("file", StringComparison.OrdinalIgnoreCase))
    {
        file = await contentPart.ReadAsStreamAsync();
    }
}

In ASP. NET Ядро, парсинг файла / формы встроен, и MultipartMemoryStreamProvider больше не существует, поэтому я реализовал это:

public async Task<IActionResult> Put(IFormFileCollection files) // files is empty list
public async Task<IActionResult> Put(IFormFile file) // file is null

// ...

var formFile = request.Form.Files.GetFile("file"); 
// formFile is null
// requests.Form.Files is empty
Stream file = formFile.OpenReadStream();

Файл можно получить через request.Form["file"], но его содержимое отображается как {����. Не знаю, смогу ли я вернуть это к своему бинарному контенту. cryptic string content

Я попробовал этот код, но файл не может быть открыт впоследствии.

var fff = request.Form["file"];
using (var stream = System.IO.File.OpenWrite("out.jpg"))
using (StreamWriter sw = new StreamWriter(stream))
{
    sw.Write(fff);
}

1 Ответ

0 голосов
/ 07 апреля 2020

Мне удалось решить проблему, используя MultipartReader вместо старого MultipartMemoryStreamProvider. Документы Microsoft и соответствующий пример GitHub очень помогли.

Это урезанная версия моего окончательного кода. Это ни в коем случае не конечная точка «общей загрузки файла», см. Приведенный выше пример, если вам нужно что-то, что может обрабатывать более разные сценарии ios.



[DisableFormValueModelBinding]
public async Task<IActionResult> Put(CancellationToken cancellationToken)
{

Stream fileStream = null;

var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), new FormOptions().MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, Request.Body);

var section = await reader.ReadNextSectionAsync();

while (section != null)
{
    var hasContentDispositionHeader =
        ContentDispositionHeaderValue.TryParse(
            section.ContentDisposition, out var contentDisposition);

    if (hasContentDispositionHeader)
    {
        if (contentDisposition.Name.Equals("file", StringComparison.OrdinalIgnoreCase))
        {
            fileStream = new MemoryStream();
            await section.Body.CopyToAsync(fileStream);
            fileStream.Position = 0;
        }
    }
    section = await reader.ReadNextSectionAsync();
}
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
    {
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            var factories = context.ValueProviderFactories;
            factories.RemoveType<FormValueProviderFactory>();
            factories.RemoveType<JQueryFormValueProviderFactory>();
        }

        public void OnResourceExecuted(ResourceExecutedContext context)
        {
        }
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...