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);
}