FormData没有来到API控制器的Post方法

时间:2018-05-29 10:41:28

标签: angular file-upload .net-core

我试图将Angular 5应用程序中的文件发送到dotnet core 2中的web api控制器,但我的模型总是空的。

如果我观看Chrome工具,我会在请求中看到以下表单有效内容:

------ WebKitFormBoundaryHbjYM4AKAkl6rQFo 内容处理:表格数据;名称=" quotationId"

4 ------ WebKitFormBoundaryHbjYM4AKAkl6rQFo 内容处理:表格数据;名称=" quotationFile&#34 ;; filename =" Analisis y Oferta E3M-v1.1.pdf" 内容类型:application / pdf

------ WebKitFormBoundaryHbjYM4AKAkl6rQFo -

ANGULAR POST

  quotationFileUpload(files: FileList, quotationId: number) {
    if (files && files[0].size > 0) {
      const formData = new FormData();

      formData.append('quotationId', quotationId.toString());
      formData.append('quotationFile', files[0]);

      this.projectService.uploadQuotation(formData).subscribe(
        response => {
          this.alertService.success('Proyecto', 'Presupuesto subido correctamente.');
        },
        error => {
          this.alertService.error('Proyecto', error.error);
        }
      );
    }
  }

角度服务方法

  public uploadQuotation(quotation: FormData) {
    return this.http.post(this.config.apiUrl + '/projects/quotations/file', quotation);
  }

DOTNET CODE

/// <summary>
/// Upload a Quotation document.
/// </summary>
/// <param name="model"></param>
[HttpPost("quotations/file")]
[ProducesResponseType(200, Type = typeof(Quotation))]
[ProducesResponseType(400, Type = typeof(string))]
[ProducesResponseType(404, Type = typeof(string))]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<ActionResult> UploadQuotation([FromForm] QuotationUploadViewModel model)
{
    try
    {
        var quotation = await _context.Quotations
                            .AsNoTracking()
                            .SingleOrDefaultAsync(c => c.QuotationId == System.Convert.ToInt32(model.QuotationId));

        if (quotation == null)
        {
            return NotFound($"Presupuesto con Id {model.QuotationId} no encontrado.");
        }

        _context.Quotations.Update(quotation);

        // Save file
        var filePath = Path.Combine(_hostingEnvironment.ContentRootPath, @"Uploads", model.QuotationFile.FileName);

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await model.QuotationFile.CopyToAsync(stream);
        }

        quotation.FileName = model.QuotationFile.FileName;
        await _context.SaveChangesAsync();

        return Ok(quotation);
    }
    catch (System.Exception ex)
    {
        _errorResponseMsg = $"No se pudo subir el Presupuesto {model.QuotationId}: {ex.Message}";
        _logger.LogError(_errorResponseMsg);
    }

    return BadRequest(_errorResponseMsg);
}

QUOTATIONUPLOADVIEWMODEL

using Microsoft.AspNetCore.Http;

namespace E3m.Api.ViewModels.E3m
{
    public class QuotationUploadViewModel
    {
        public string QuotationId { get; set; }
        public IFormFile QuotationFile { get; set; }
    }
}

使用此代码,web api方法中的模型属性始终为null。

任何关于这个问题的想法? 此致

2 个答案:

答案 0 :(得分:0)

我不确定这会对您有所帮助,但这是我将文件发布到ASP.NET并将其保存到MSSQL数据库的方式。

  

角度部分:

MyService.ts:

SendFile(filescan, id: number) {
    if (filescan == null) { return Observable.of(0); }
    let fileList: FileList = filescan.target.files;
    if (fileList.length > 0) {
        let file: File = fileList[0];
        let formData: FormData = new FormData();
        formData.append('uploadFile', file, file.name);
        formData.append('id', id.toString());
        let headers = new HttpHeaders();
        return this._http.post<number>('faktura/savefile', formData, { headers: headers });
        }
    }

MyComponent.ts:

let answer: number;
this._Service.SendFile(this.fileScan, this.zr.ID)
    .takeUntil(this.ngUnsubscribe)
    .subscribe(
        result => { answer = result; },
        error => { this.errorMessage = <any>error; },
        () => {});
  

ASP.NET部分

控制器:

[HttpPost]
    public IHttpActionResult savefile()
    {
        var httpRequest = HttpContext.Current.Request;
        if (httpRequest.Files.Count > 0)
        {
            foreach (string file in httpRequest.Files)
            {
                var postedFile = httpRequest.Files[file];
                var contentType = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf(".") + 1);
                var id = Convert.ToInt32(httpRequest["id"]);
                byte[] Content = new byte[(int)postedFile.InputStream.Length];
                postedFile.InputStream.Read(Content, 0, (int)postedFile.InputStream.Length);                    
                var message = "";
                var r = _fileService.SaveFile(id, Content, contentType, ref message);
                if (message.Length > 0)
                {
                    return InternalServerError(new Exception(message));
                }
                else
                {
                    return Ok(r);
                }
            }
        }
        return Ok();
    }

服务:

public int SaveFile(int id, byte[] content, string contentType, ref string message)
{
    int result = 0;
    ConnectionStringSettings mySetting = ConfigurationManager.ConnectionStrings["MyConnection"];
    SqlConnection con = new SqlConnection(mySetting.ConnectionString);
    using (con)
    {
        con.Open();
        SqlTransaction transaction = con.BeginTransaction();
        try
        {           
            var query = "spSaveFiles";
            var parametri = new SQLHelper.SQLParametri
            {
                { "@ID", id },
                { "@ScanPrilog", content },
                { "@ContentType", contentType }
            };
            result = SQLHelper.ExecuteNonQuery(CommandType.StoredProcedure, query, transaction, parametri);
            transaction.Commit();
        }
        catch (SqlException sqlError)
        {
            transaction.Rollback();
            message = sqlError.Message;
            result = 0;
        }
        return result;
    }
}

答案 1 :(得分:0)

我发现问题...在Angular中我通过拦截器向'Content-Type':'application / json'添加了一个标题。删除此标头可以正常工作。

由于