Я пытаюсь отправить файл из приложения Angular 5 на свой контроллер веб-API в .NET Core 2, но моя модель всегда пуста.
Если я смотрю инструменты Chrome, я вижу в запросе следующую полезную нагрузку формы:
------WebKitFormBoundaryHbjYM4AKAkl6rQFo
Content-Disposition: form-data; name = "quotationId"
4
------WebKitFormBoundaryHbjYM4AKAkl6rQFo
Content-Disposition: form-data; name = "quotationFile"; filename = "Analisis y Oferta E3M-v1.1.pdf"
Content-Type: application/pdf
------WebKitFormBoundaryHbjYM4AKAkl6rQFo--
Угловой 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);
}
Код .NET:
/// <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);
}
ЦИТАТА ЗАГРУЗКАМОДЕЛЬ
using Microsoft.AspNetCore.Http;
namespace E3m.Api.ViewModels.E3m
{
public class QuotationUploadViewModel
{
public string QuotationId { get; set; }
public IFormFile QuotationFile { get; set; }
}
}
В этом коде свойства модели всегда равны нулю в методе веб-API.
Есть идеи о том, как эта проблема? С Уважением





Не уверен, что это поможет вам, но именно так я отправляю файлы в ASP.NET и сохраняю их в базе данных MSSQL.
Angular part:
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 part
Контроллер:
[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;
}
}
Я обнаружил проблему ... в Angular я добавлял заголовок ко всем своим запросам с помощью Content-Type: application / json через перехватчик. Удаление этого заголовка работает нормально.
Спасибо