typescript - Hogyan lehet adatot és több fájlt feltölteni Angularból .net core Web Api-ba
A szerverem a .Net Core 2.1.402-t használja
Itt van a C# osztályom:
public class SampleDetailsDto
{
public Guid Id{ get; set; }
public string Text { get; set; }
public IEnumerable<string> ImageUrls { get; set; }
public IFormCollection Images { get; set; }
}
Itt van az én C# vezérlőm
[HttpPut]
[Route("{id:guid}")]
public async Task<IActionResult> UpdateAsync([FromRoute]Guid id, [FromForm] SampleDetailsDtodto)
{
Console.WriteLine(dto.Text);
Console.WriteLine(dto.Images.Length);
return OK();
}
Az NSwag-ot használom a kliens szolgáltatás generálására, de jelenleg van egy hiba (https://github.com/RSuter/NSwag/issues/1421#issuecomment-424480418) a több fájl feltöltésével kapcsolatban, ezért kiterjesztettem a frissítési metódust, hogy elkészítsem a sajátomat, íme a kód:
public update(id: string, dto: SampleDetailsDto | null | undefined): Observable<SampleDetailsDto | null> {
let url_ = this._baseUrl + "/api/v1/Sample/{id}";
if (id === undefined || id === null)
throw new Error("The parameter 'id' must be defined.");
url_ = url_.replace("{id}", encodeURIComponent("" + id));
url_ = url_.replace(/[?&]$/, "");
let options_: any = {
observe: "response",
responseType: "blob",
headers: new HttpHeaders({
"Accept": "application/json"
})
};
return _observableFrom(this.transformOptions(options_)).pipe(_observableMergeMap(transformedOptions_ => {
return this._http.put<SampleDetailsDto>(url_,dto, transformedOptions_);
})).pipe(_observableMergeMap((response_: any) => {
return this.transformResult(url_, response_, (r) => this.processUpdate(<any>r));
})).pipe(_observableCatch((response_: any) => {
if (response_ instanceof HttpResponseBase) {
try {
return this.transformResult(url_, response_, (r) => this.processUpdate(<any>r));
} catch (e) {
return <Observable<SampleDetailsDto | null>><any>_observableThrow(e);
}
} else
return <Observable<SampleDetailsDto | null>><any>_observableThrow(response_);
}));
}
Szeretnék egyszerre több fájlt és adatot feltölteni, ebben az esetben az összes kép a SampleDetailsDto-hoz van kapcsolva. De elképzelhetjük, hogy ilyen típusú eset is előfordulhat:
public class SampleDetailsDto
{
public Guid Id{ get; set; }
public string Text { get; set; }
public IEnumerable<ChildSampleDetailsDto> Children{ get; set; }
}
public class ChildSampleDetailsDto
{
public Guid Id{ get; set; }
public string Text { get; set; }
public IEnumerable<string> ImageUrls { get; set; }
public IFormCollection Images { get; set; }
}
Lehetséges adatot és több fájlt küldeni egy .NET Core Web API-hoz?
Köszönöm
Válasz #1
Használd a IFormFile-t és a [FromForm]-ot, és ne férj hozzá a kéréshez a fájlok kinyeréséhez.
Angular kód:
public sendFiles(files: File[], [...]): Observable<any> {
const formData = new FormData();
formData.append('files', files); // add all the other properties
return this.http.post('http://somehost/someendpoint/fileupload/', formData);
}
ASP.NET Core kód:
public class MyFileUploadClass
{
public IFormFile[] Files { get; set; }
// other properties
}
[HttpPost("fileupload")]
public async Task<IActionResult> FileUpload([FromForm] MyFileUploadClass @class) // -> property name must be the same used as formdata key
{
// do the magic here
return NoContent();
}
Válasz #2
Olvassa el a választ maherjendoubi-tól itt: https://forums.asp.net/t/2099194.aspx?Net+Core+Web+API+How+to+upload+multi+part+form+data
public ActionResult CreateDocument()
{
foreach(var key in Request.Form.Keys)
{
var data = JsonConvert.DeserializeObject<ChildSampleDetailsDto>(Request.Form[key]);
var file = Request.Form.Files["file" + key];
}
return Ok();
}
Az angular részhez használjon egy HttpRequest-et:
const sendable = new FormData();
for (let i; i < files.length; i++) {
sendable.append('filedata' + i, files[i], files[i].name);
sendable.append('data' + i, JSON.stringify(data[i]));
}
const request = new HttpRequest(item.method,
item.url,
sendable,
{
reportProgress: true
});
// this._http: HttpClient
this._http.request(request)
.subscribe((event: any) => {
if (event.type === HttpEventType.UploadProgress) {
// on progress code
}
if (event.type === HttpEventType.Response) {
// on response code
}
}, error => {
// on error code
});
