【问题标题】:unable to send IFormFile to ASP.Net Core Web API using C# client无法使用 C# 客户端将 IFormFile 发送到 ASP.Net Core Web API
【发布时间】:2017-06-16 16:24:23
【问题描述】:

我有一个 ASP.Net Core Web API,控制器的 POST 方法定义如下:

[HttpPost("SubmitFile")]
public async Task<IActionResult> SubmitFile(IFormFile file)
{
}

我有一个调用 API SubmitFile() 方法的客户端方法,定义如下:

[HttpPost]
public async Task<IActionResult> Index(ICollection<IFormFile> files)
{
     using (var client = new HttpClient())
     {
         client.BaseAddress = new Uri(_options.SiteSpecificUrl);

         foreach (var file in files)
         {
             if (file.Length <= 0)
                 continue;

             var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
             var fileContent = new StreamContent(file.OpenReadStream());
             fileContent.Headers.Add("X-FileName", fileName);
             fileContent.Headers.Add("X-ContentType", file.ContentType);

             var response = await client.PostAsync(_options.WebApiPortionOfUrl, fileContent);
         }
     }

    return View();
}

执行客户端发送时,在服务器端 SubmitFile() 中的断点显示文件参数为空。如何正确发送文件?保留服务器端 API 很重要,因为我让 Swashbuckle/Swagger 正确生成了可以发送文件的 UI。

【问题讨论】:

  • 我很确定您不能接受接口作为模型绑定参数。您必须使用具体类。
  • 您指的是 SubmitFile(IFormFile 文件)?请解释...
  • 不,比如List&lt;IFormFile&gt;,而不是ICollection。虽然,阅读文档,它可以接受IEnumerable&lt;IFormFile&gt;。见docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads

标签: c# asp.net-core .net-core asp.net-core-webapi


【解决方案1】:

我找到了几种方法来做到这一点。这里是最简单的。请注意,这是一个 ASP.Net Core 客户端解决方案:

[HttpPost]
public async Task<IActionResult> Index(ICollection<IFormFile> files)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(_options.SiteSpecificUrl);

        foreach (var file in files)
        {
            if (file.Length <= 0)
                continue;

            var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');

            using (var content = new MultipartFormDataContent())
            {
                content.Add(new StreamContent(file.OpenReadStream())
                {
                    Headers =
                    {
                        ContentLength = file.Length,
                        ContentType = new MediaTypeHeaderValue(file.ContentType)
                    }
                }, "File", fileName);

                var response = await client.PostAsync(_options.WebApiPortionOfUrl, content);
            }
        }
    }
}

从 .cshtml 页面调用此控制器方法,如下所示:

@{
    ViewData["Title"] = "Home Page";
}

<form method="post" asp-action="Index" asp-controller="Home" enctype="multipart/form-data">
    <input type="file" name="files" multiple />
    <input type="submit" value="Upload" />
</form>

此表单显示两个按钮,“选择文件”,显示“选择文件”对话框,和“上传”,调用 HomeController.Index 方法。

【讨论】:

    【解决方案2】:

    这对我有用:

    前端:

    HTML/CSS:

    <div id="" class="col-xs-12 info-box">
    <div class="col-xs-12">  
        <a role="button" data-toggle="collapse" href="#upload-sample" aria-expanded="false"> 
            <h3><span class="glyphicon glyphicon-upload"></span> Upload de Arquivo</h3>
        </a>
    </div>   
    <div id="upload-sample" class="col-xs-12 collapse">  
        <form method="post" enctype="multipart/form-data">
            <div>
                <div class="form-group attach" style="width: 100%;">
                    <label>Select Excel File <button type="button" id="btnDownloadTemplate">(Download Template)</button></label>
                    <div class="col-md-12"><input type="file" id="fUpload" name="files" multiple class="form-control" style="max-width: 400px;" /></div>
                </div>                
                <div class="filter-button" style="width: 100%;">                     
                    <button onclick="AJAXSubmit(this); return false;" id="btnUpload" class="btn btn-primary">Send File and update data</button>
                </div>
            </div>
        </form>
    </div>      
    

    JavaScript:

    async function AJAXSubmit(oFormElement) {
        const files = $('#fUpload').prop("files");
        const fdata = new FormData();
        for (var i = 0; i < files.length; i++) {
            fdata.append("files", files[i]);
        }
        if (files.length > 0) {
            Block();
            $.ajax({
                type: "POST",
                url: "/{{controllerName}}/OnPostUpload?handler=Upload",
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN",
                        $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                data: fdata,
                contentType: false,
                processData: false,
                success: function (response) {
                    document.getElementById("fUpload").value = "";
                    //Unblock();                    
                    //toastr.success(response, "File processed successfully");
                    FilterHandlebarsF.Search(this, true);
                },
                error: function (response) {                    
                    document.getElementById("fUpload").value = "";
                    //Unblock();
                    //toastr.warning(response, "Error on processing");
                }
            });
        }
        else {
            //toastr.warning("Please, select a file.");
        }
    }
    

    后端:

    Startup.cs:services.AddAntiforgery(o =&gt; o.HeaderName = "XSRF-TOKEN");

    控制器:

    public ActionResult OnPostUpload(List<IFormFile> files)
        {
            try
            {
                var file = files.FirstOrDefault();
                var inputstream = file.OpenReadStream();
    
                XSSFWorkbook workbook = new XSSFWorkbook(stream);
    
                var FIRST_ROW_NUMBER = {{firstRowWithValue}};
    
                ISheet sheet = workbook.GetSheetAt(0);
                // Example: var firstCellRow = (int)sheet.GetRow(0).GetCell(0).NumericCellValue;
    
                for (int rowIdx = 2; rowIdx <= sheet.LastRowNum; rowIdx++)
                   {
                      IRow currentRow = sheet.GetRow(rowIdx);
    
                      if (currentRow == null || currentRow.Cells == null || currentRow.Cells.Count() < FIRST_ROW_NUMBER) break;
    
                      var df = new DataFormatter();                
    
                      for (int cellNumber = {{firstCellWithValue}}; cellNumber < {{lastCellWithValue}}; cellNumber++)
                          {
                             //business logic & saving data to DB                        
                          }               
                     }
            }
            catch(Exception ex)
            {
                throw new FileFormatException($"Error on file processing - {ex.Message}");
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2018-12-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-06
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-30
      相关资源
      最近更新 更多