Как я могу расширить и добавить интерфейс IFormFile в .NET Core.Необходимо добавить данные в сериализованный массив при отправке запроса AJAX - PullRequest
0 голосов
/ 18 ноября 2018

Мне нужно загрузить файл, используя ядро ​​.net.

Я использую многочастную форму и AJAX.

Однако у меня есть уникальное требование. Мне нужно иметь возможность добавлять данные в сериализованный массив и затем связывать их с контроллером через запрос POST ajax и привязку модели.

Мне нужно добавить идентификатор, который я передаю контроллеру. На основании идентификатора я решаю, к какой строке таблицы я сохраняю данные загруженного файла.

Мой контроллер, на который я отправляю сообщения:

 [HttpPost]
        public async Task<IActionResult> File(List<IFormFile> files)
        {
            long size = files.Sum(f => f.Length);


            var filePath = Path.GetTempFileName();


            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await formFile.CopyToAsync(stream);
                    }
                }
            }

            string fpath = filePath;

            var query = from d in db.TableA
                        where d.File == null && d.id == id // This is where I need to compare the ID
                        select d;


            foreach (TableA details in query)
            {
                details.File = filePath;
            }
            try
            {
                await db.SaveChangesAsync(); // await needed to hold execution
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

            }


            return RedirectToAction("View");
        }

где d.File == null && d.id == id // Здесь мне нужно сравнить ID

Форма для нескольких деталей:

<form method="post" id="typea" enctype="multipart/form-data" asp-controller="Main" asp-action="File">
<label class="btn btn-info"> Upload your document <input type="file" name="files" onchange="this.form.submit()" hidden />
</label>
</form>

Мой звонок по Ajax:

 $(document).ready(function () {
        $('#typea').click(function () {


            event.preventDefault();


            var $form = $(this);
            var serializedData = $form.serializeArray();
            serializedData.push({ name: "ID", value: "typea" });
            $.ajax({
                url: "Main/File",
                type: "POST",
                data: serializedData

            });

        });

Моя проблема заключается в следующем:

Если я нажимаю массив, я не могу рассчитывать на интерфейс IFormFile для привязки модели.

Можно ли как-нибудь расширить интерфейс IFormFIle?

Или есть способ, которым я могу сделать это без использования IFormFile. Я пытался написать собственную модель, ссылающуюся на интерфейс IFormFIle, но не смог.

public interface IFormFile
{
    string ContentType { get; }
    string ContentDisposition { get; }
    IHeaderDictionary Headers { get; }
    long Length { get; }
    string Name { get; }
    string FileName { get; }
    Stream OpenReadStream();
    void CopyTo(Stream target);
    Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
}

Я не мог использовать методы интерфейса, что очевидно. Указатели пожалуйста:).

1 Ответ

0 голосов
/ 19 ноября 2018
  1. Вам не нужно реализовывать (расширять) интерфейс IFormFile, обертка по составу предпочтительнее наследования.Просто создайте фиктивный POCO для хранения информации:

    public class IFormFilesWrapper{
    
        public string Id {get;set;}  // you might change the type to Guid / int /e.t.c
    
        public IList<IFormFile> Files {get;set;}
    }
    

    и метод действия будет:

    [HttpPost]
    public async Task<IActionResult> File(IFormFilesWrapper filesWrapper)
    {
        var id = filesWrapper.Id;  // here's the Id posted by client
    
        long size = filesWrapper.Files.Sum(f => f.Length);
    
        var filePath = Path.GetTempFileName();
    
        foreach (var formFile in filesWrapper.Files)
        {
            if (formFile.Length > 0)
            {
                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }
    
        // ...
    }
    
  2. В качестве примечания, если я правильно помню$form.serializeArray() плохо работает для multipart/form-data.Поэтому я использую простой FormData для генерации полезной нагрузки:

    $(document).ready(function () {
        $('#typea>button').click(function () {
    
            event.preventDefault();
    
            var form = document.querySelector("#typea");
            var formData = new FormData(form);
            formData.append("ID","typea");
    
            var xhr = new XMLHttpRequest();
            xhr.open("POST","Main/File");
            xhr.send(formData);
        });
    });
    

Скриншот:

enter image description here

...