Как получить значение Iformfile из JObject?

Я использую последнее ядро ​​.net, у меня есть приложение mvc и веб-приложение Api, поэтому приложение mvc принимает запрос, и все операции над базой данных выполняются приложением веб-API. Я застрял большую часть времени в связи с IFormFile для загрузки изображения, так или иначе. Мне удалось получить данные изображения и привязать его к ViewModel, однако, когда я передаю ViewModel как PostAsJsonAsync в контроллер веб-API, у которого параметр viewmodel, он не работает, поэтому я перешел на JObject, и теперь моя проблема заключается в том, как извлечь свойство IFormFile. из JObject как IFormFile, я сталкиваюсь с ошибкой InvalidCastException. Вот мой код

//HTML File
 <div class="control-label col-md-2">
                    @Html.Label("Image")
                </div>
                <div class="col-md-3 imgdrop">
                    <input type="file" id="file" name="file"class="form-control-file" />
                    <div class="img-wrap ">
                        <span class="close">&times;</span>
                        <img src="..." alt="..."  id="imgInp" class="img-fluid" />
                    </div>
                </div>

  $("#SaveDetailsId").on("click", function () {



                var formdata = new FormData();
                var table = $("#ItemListTable").DataTable();
 $.each(tableData, function (index, item) {

                    name = 'ItemList[' + index + '].SkuList'; // construct the name
                    value = item[0];
});

                formdata.append("ImageFile", jQuery("#file").get(0).files[0]);

$.ajax({
                    //headers: {
                    //    'Accept': 'application/json',
                    //    'Content-Type': 'application/json'
                    //},
                    url: "/Test/Test",
                    type: "POST",
                    data: formdata,
                    contentType: false,
                    processData: false,
                    success: function (response) {
...

  });
            });

//ViewModel
public class Test
{
   public IFormFile ImageFile {get;set;}
.
.
.
}

//MVC Controller
 [HttpPost]
        public async Task<IActionResult> BuyerCreative([FromForm]Test _viewModel)
        {
            _viewModel.Ad = _viewModel.Ad;
            using (var client = new HttpClient())
            {
                //Passing service base url  
                client.BaseAddress = new Uri(Baseurl);

                client.DefaultRequestHeaders.Clear();

                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage Res = await client.PostAsJsonAsync("api/Test/Test", _viewModel);                

                if (Res.IsSuccessStatusCode)
                {
                         }
                //returning the employee list to view  
                return View(_viewModel);
            }

        }
//Let me know if there is a way to bind ViewModel instead of JObject
//WEbApi
[Route("api/Test/Test/")]
        [HttpPost]
        public IActionResult Test([FromBody] JObject data)
        {
            try
            {

               _Repository.AddDetails(data);

                return Ok();
            }
            catch (Exception pException)
            {
                return BadRequest(pException.Message);
            }
        }

//And Lastly my repository


 public void AddDetails(JObject data)
{

 DBContext.Items _items = new DBContext.Items();
 _items.Number = Convert.ToInt32(((JValue)data.GetValue("Number")).Value); 

// I 'm stuck over here, how to get the IFormFile, I tried various options

 IFormFile file = (IFormFile)((JValue)data.GetValue("ImageFile"));

 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionString);

                    // Create a blob client for interacting with the blob service.
                    blobClient = storageAccount.CreateCloudBlobClient();
                    blobContainer = blobClient.GetContainerReference(blobContainerName);
                    blobContainer.CreateIfNotExistsAsync();
                    blobContainer.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });

                    var fileContent = reader.ReadToEnd();
                    var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
                    fileName = parsedContentDisposition.FileName;

                    CloudBlockBlob blob = blobContainer.GetBlockBlobReference(fileName);
                    blob.UploadFromStreamAsync(file.OpenReadStream());

}

2 ответа

Во-первых, не связывайтесь с JObject, Создайте реальную модель представления и привязайтесь к ней.

public class ItemViewModel
{
    public int Number { get; set; }
    public byte[] File { get; set; }
}

Затем:

public void AddDetails([FromBody]ItemViewModel data)

Во-вторых, чтобы опубликовать файл через JSON, вы должны отправить его в формате base64. byte[] (что сделает его строкой). Связыватель модели автоматически base64-декодирует его обратно в истинное byte[], если это то, к чему вы привязываете это через вашу модель представления.

Если вы не хотите, чтобы base64-кодировал его на стороне клиента, вы должны опубликовать его как multipart/form-data, в этом случае вам нужно будет привязать опубликованный файл к IFormFile, Что означает, что вы измените File свойство в классе модели представления выше, чтобы:

public IFormFile File { get; get; }

Поскольку вы упомянули свойство, скажем, есть класс со свойством:

public class MyData
{
    public IFormFile File { get; set; }
}

Теперь я могу использовать это в контроллере:

public IActionResult UploadFile([FromForm]MyData data)
{

}

Ваш data.File теперь будет содержать файл, если вы передадите данные формы с правильным ключом File,

Другие вопросы по тегам