Home > Enterprise >  How to send object and file at the sime time from Angular to .net api?
How to send object and file at the sime time from Angular to .net api?

Time:04-15

I Try to send object and file at the same time to .net api but it dont work.

I am trying to send data with FormData on angular side but FormData does not accept objects. When I don't send it with FormData, I can't receive the Files on the .net side.

How can I send the files and the object to the .net side at the same time?

angular :

const formData = new FormData();
formData.append('type',this.form.get('type').value)
formData.append('productId',this.form.get('product').value);
formData.append('serialNo',this.form.get('serialNo').value);
formData.append('companyId',this.form.get('company').value);
formData.append('unitPrice',this.form.get('unitPrice').value.toString().replace('.',','));
formData.append('description',this.form.get('description').value);
formData.append('properties',this._helperService.mapToObj(this.properties))

const files = this.form.get('files').value as FileList;
const fileArr = Array.from(files);
if(fileArr.length > 0){
  fileArr.forEach(f => formData.append('files',f))
}

this._stockReceiptService.saveStockReceipt(formData).pipe(takeUntil(this.subject)).subscribe(resp => {
  this.success.text = "Stok girişi kaydedildi";
  this.success.fire();
  console.log("Apiden gelen => ", resp);
}, err => {
  this.error.text = "Stok girişi yapılırken hata oluştu";
  this.error.fire();
});

}

SaveStockReceipt Service:

saveStockReceipt(post: any): Observable<any>{
return this._http.post<any>(this.apiURL   '/stock/stockReceipt',post);
}

.net model

public class CreateStockVModel
{
[Required(ErrorMessage = "Type alanı zorunlu alandır.")]
public int Type { get; set; }

[Required(ErrorMessage = "ProductId alanı zorunlu alandır.")]
public int ProductId { get; set; }

[Required(ErrorMessage = "SerialNo alanı zorunlu alandır.")]
public string? SerialNo { get; set; }

[Required(ErrorMessage = "CompanyId alanı zorunlu alandır.")]
public int CompanyId { get; set; }

public decimal? UnitPrice { get; set; }
public string? Description { get; set; }
public List<IFormFile>? Files { get; set; }
public Dictionary<int,int>? Properties { get; set; }
}

controller

[HttpPost]
public async Task<IActionResult> StockReceipt([FromForm] CreateStockVModel vModel)
{
    return Ok(vModel);
}

CodePudding user response:

Maybe you should try to convert C# model to TS interface and put it to saveStockReceipt instead of post: any

CodePudding user response:

I will write the solution in an abstract way because it will take time. But basically, the workflow will be as follows:

Send the files as a stream with the request to the backend:

<input type="file" name="file" id="file"(change)="onFileChanged($event)" multiple />
....


export class MyComponent {
   public files: any[];
   ...
   onFileChanged(event: any) {
    this.files.push(event.target.files[0]);
  }
  upload() {
    const formData = new FormData();
    this.files.forEach(file => formData.append(this.file.name, this.file, this.file.name));
    ... Apend the rest
    this.httpClient.post(url, formData, { headers: headers }).subscribe(...);
  }
}

You need to read the files in the backend from the request:

   [HttpPost]
   public async Task<IActionResult> StockReceipt([FromForm] CreateStockVModel vModel)
   {
      var files = this.Request.Form.Files[0]; // you can iterate throw other files
      if (files.Length > 0)
      {
          var fileName = ContentDispositionHeaderValue.Parse(files.ContentDisposition).FileName.Trim('"');
          var fullPath = Path.Combine(pathToSave, fileName);
          using (var stream = new FileStream(fullPath, FileMode.Create))
          {
              // here you have the stream
          }
    }
      return Ok();
   }

For more information, see this link: https://code-maze.com/upload-files-dot-net-core-angular/

CodePudding user response:

It's because you defined the Files as List but sending files as single file, so to correct the code replace the following:

if(fileArr.length > 0){
  fileArr.forEach(f => formData.append('files',f))
}

with:

let files = [];
if(fileArr.length > 0){
  fileArr.forEach(f => files.push(f));
  formData.append('files', files);
}
  • Related