{"id":29193,"date":"2019-01-23T00:00:00","date_gmt":"2019-01-22T23:00:00","guid":{"rendered":"https:\/\/blexin.com\/upload-e-download-di-file-con-angular-e-asp-net-core\/"},"modified":"2021-05-20T19:27:42","modified_gmt":"2021-05-20T17:27:42","slug":"uploading-and-downloading-files-with-angular-and-asp-net-core","status":"publish","type":"post","link":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/","title":{"rendered":"Uploading and Downloading files with Angular and Asp.Net Core"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"29180\" data-permalink=\"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/attachment\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-29180\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A frequently required activity, in the projects I work on, is the&nbsp;management of the upload and download of files in Angular. There are different ways to develop these functionalities: the best approach often depends on the available API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose you&nbsp;have some API written in Asp.Net Core, particularly a controller with three actions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Upload<\/strong>, to receive a file a save it in the folder.\/wwwroot\/upload;<\/li><li><strong>Download<\/strong>, to recover a file from the folder.\/wwwroot\/upload;<\/li><li><strong>Files<\/strong>, to obtain the list of files present in .\/wwwroot\/upload.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A possible implementation of the controller may be the following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace BackEnd.Controllers\n{\n\u00a0\u00a0\u00a0&#x5B;Route(&quot;api&quot;)]\n\u00a0\u00a0\u00a0&#x5B;ApiController]\n\u00a0\u00a0\u00a0public class UploadDownloadController: ControllerBase\n\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private IHostingEnvironment _hostingEnvironment;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public UploadDownloadController(IHostingEnvironment environment) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_hostingEnvironment = environment;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;HttpPost]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;upload&quot;)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public async Task&lt;iactionresult&gt; Upload(IFormFile file)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var uploads = Path.Combine(_hostingEnvironment.WebRootPath, &quot;uploads&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if(!Directory.Exists(uploads))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Directory.CreateDirectory(uploads);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (file.Length &gt; 0) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var filePath = Path.Combine(uploads, file.FileName);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0using (var fileStream = new FileStream(filePath, FileMode.Create)) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0await file.CopyToAsync(fileStream);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Ok();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;HttpGet]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;download&quot;)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public async Task&lt;iactionresult&gt; Download(&#x5B;FromQuery] string file) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var uploads = Path.Combine(_hostingEnvironment.WebRootPath, &quot;uploads&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var filePath = Path.Combine(uploads, file);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (!System.IO.File.Exists(filePath))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return NotFound();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var memory = new MemoryStream();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0using (var stream = new FileStream(filePath, FileMode.Open))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0await stream.CopyToAsync(memory);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memory.Position = 0;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return File(memory, GetContentType(filePath), file);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;HttpGet]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;files&quot;)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public IActionResult Files() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var result =\u00a0 new List&lt;string&gt;();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var uploads = Path.Combine(_hostingEnvironment.WebRootPath, &quot;uploads&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if(Directory.Exists(uploads))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\u00a0 \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var provider = _hostingEnvironment.ContentRootFileProvider;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach (string fileName in Directory.GetFiles(uploads))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var fileInfo = provider.GetFileInfo(fileName);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result.Add(fileInfo.Name);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Ok(result);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \n\u00a0\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private string GetContentType(string path)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var provider = new FileExtensionContentTypeProvider();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string contentType;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if(!provider.TryGetContentType(path, out contentType))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0contentType = &quot;application\/octet-stream&quot;;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return contentType;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">As you can see, there\u2019s nothing particularly complex. Focus your attention to the&nbsp;<em>FileExtensionContentTypeProvider<\/em>&nbsp;from .Net Core: it allows you to obtain the content type from file extension.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, we can create an Angular project with the CLI, with which&nbsp;we want to upload files, display and download them. Moreover, we will show the progress during download and upload, using one of the Angular HttpClient functionalities.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We will create a specific component for each operation, Upload and Download, and we will use it from a FileManager component, that shows the list of downloaded files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The three components share a service, in which we implement the HTTP calls to our API:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nimport { Injectable } from &#039;@angular\/core&#039;;\nimport { HttpClient, HttpRequest, HttpEvent, HttpResponse } from &#039;@angular\/common\/http&#039;;\nimport { Observable } from &#039;rxjs&#039;;\n\u00a0\n@Injectable()\nexport class UploadDownloadService {\n\u00a0\u00a0private baseApiUrl: string;\n\u00a0\u00a0private apiDownloadUrl: string;\n\u00a0\u00a0private apiUploadUrl: string;\n\u00a0\u00a0private apiFileUrl: string;\n\u00a0\n\u00a0\u00a0constructor(private httpClient: HttpClient) {\n\u00a0\u00a0\u00a0\u00a0this.baseApiUrl = &#039;http:\/\/localhost:5001\/api\/&#039;;\n\u00a0\u00a0\u00a0\u00a0this.apiDownloadUrl = this.baseApiUrl + &#039;download&#039;;\n\u00a0\u00a0\u00a0\u00a0this.apiUploadUrl = this.baseApiUrl + &#039;upload&#039;;\n\u00a0\u00a0\u00a0\u00a0this.apiFileUrl = this.baseApiUrl + &#039;files&#039;;\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public downloadFile(file: string): Observable&lt;HttpEvent&lt;Blob&gt;&gt; {\n\u00a0\u00a0\u00a0\u00a0return this.httpClient.request(new HttpRequest(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#039;GET&#039;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0`${this.apiDownloadUrl}?file=${file}`,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0null,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reportProgress: true,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0responseType: &#039;blob&#039;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}));\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public uploadFile(file: Blob): Observable&lt;HttpEvent&lt;void&gt;&gt; {\n\u00a0\u00a0\u00a0\u00a0const formData = new FormData();\n\u00a0\u00a0\u00a0\u00a0formData.append(&#039;file&#039;, file);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0return this.httpClient.request(new HttpRequest(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#039;POST&#039;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.apiUploadUrl,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0formData,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reportProgress: true\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}));\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public getFiles(): Observable&lt;string&#x5B;]&gt; {\n\u00a0\u00a0\u00a0\u00a0return this.httpClient.get&lt;string&#x5B;]&gt;(this.apiFileUrl);\n\u00a0\u00a0}\n\u00a0\u00a0\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Compared to the classical use of HttpClient, that you can display in the method&nbsp;<em>getFiles()<\/em>, in&nbsp;<em>dowloadFile()<\/em>&nbsp;and&nbsp;<em>uploadFile()<\/em>&nbsp;we use the&nbsp;<em>request()<\/em>&nbsp;method, that permits us to specify a HttpRequest with all its options, among them the option&nbsp;<em>reportProgress<\/em>&nbsp;set on true. This option enables us to receive updates on the exchange data status between client and server. How? We can see that in our Upload component:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nimport { Component, Output, EventEmitter, Input, ViewChild, ElementRef } from &#039;@angular\/core&#039;;\nimport { UploadDownloadService } from &#039;src\/app\/services\/upload-download.service&#039;;\nimport { HttpEventType } from &#039;@angular\/common\/http&#039;;\nimport { ProgressStatus, ProgressStatusEnum } from &#039;src\/app\/models\/progress-status.model&#039;;\n\u00a0\n@Component({\n\u00a0\u00a0selector: &#039;app-upload&#039;,\n\u00a0\u00a0templateUrl: &#039;upload.component.html&#039;\n})\n\u00a0\nexport class UploadComponent {\n\u00a0\u00a0@Input() public disabled: boolean;\n\u00a0\u00a0@Output() public uploadStatus: EventEmitter&lt;progressstatus&gt;;\n\u00a0\u00a0@ViewChild(&#039;inputFile&#039;) inputFile: ElementRef;\n\u00a0\n\u00a0\u00a0constructor(private service: UploadDownloadService) {\n\u00a0\u00a0\u00a0\u00a0this.uploadStatus = new EventEmitter&lt;ProgressStatus&gt;();\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public upload(event) {\n\u00a0\u00a0\u00a0\u00a0if (event.target.files &amp;&amp; event.target.files.length &gt; 0) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const file = event.target.files&#x5B;0];\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.uploadStatus.emit({status: ProgressStatusEnum.START});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.service.uploadFile(file).subscribe(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (data) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0switch (data.type) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case HttpEventType.UploadProgress:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.uploadStatus.emit( {status: ProgressStatusEnum.IN_PROGRESS, percentage: Math.round((data.loaded \/ data.total) * 100)});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case HttpEventType.Response:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.inputFile.nativeElement.value = &#039;&#039;;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.uploadStatus.emit( {status: ProgressStatusEnum.COMPLETE});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.inputFile.nativeElement.value = &#039;&#039;;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.uploadStatus.emit({status: ProgressStatusEnum.ERROR});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0}\n}\n\u00a0\n&lt;\/progressstatus&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">As you can see, the subscription to the observable returned from the HttpClient gives us an HttpEvent type object, which property&nbsp;<em>type<\/em>&nbsp;can acquire one of these five values:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Sent<\/strong>, when&nbsp;the request has been sent&nbsp;<\/li><li><strong>UploadProgress<\/strong>, when&nbsp;the upload is in progress;<\/li><li><strong>ResponseHeader<\/strong>, when&nbsp;status code of headers has been received&nbsp;<\/li><li><strong>DownloadProgress<\/strong>, when the download is in progress;<\/li><li><strong>Response<\/strong>, when the response has been received;<\/li><li><strong>User<\/strong>, when a custom event is raised from an interceptor or the backend.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to level out events between upload and download and abstract us from the http library, we add our enumeration and our interface to the project:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nexport interface ProgressStatus {\n\u00a0\u00a0status: ProgressStatusEnum;\n\u00a0\u00a0percentage?: number;\n}\n\u00a0\nexport enum ProgressStatusEnum {\n\u00a0\u00a0START, COMPLETE, IN_PROGRESS, ERROR\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In the component you can see the use: we simply emit the START as the operation starts, IN_PROGRESS in correspondence of UploadProgress, COMPLETE in correspondence of Respose and ERROR in event of an error<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The template has a&nbsp;hidden input file and a button \u201cUPLOAD\u201d. Clicking on the button, the input selection window will open, allowing the user to select a file. On the input change, we recall the component upload method.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;div class=&quot;container-upload&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;button &#x5B;disabled]=&quot;disabled&quot; &#x5B;ngClass]=&quot;{&#039;disabled&#039;: disabled}&quot; class=&quot;button upload&quot; (click)=&quot;inputFile.click()&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0UPLOAD\n\u00a0\u00a0\u00a0\u00a0&lt;\/button&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;input name=&quot;file&quot; id=&quot;file&quot;(change)=&quot;upload($event)&quot; type=&quot;file&quot; #inputFile hidden&gt;\n&lt;\/div&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">As the operation ends, both in case of success and of error, you need to clean out selection input, or it would not be possible to make the upload of the same file consecutively. To do that, you can use both&nbsp;<em>ReactiveForm<\/em>&nbsp;and associate it a&nbsp;<em>FormControl<\/em>&nbsp;to the input, and with&nbsp;<em>ngModel<\/em>, cleaning out the bound property.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you don\u2019t want to involve the form management for so little and accepting to sully the component logic, you can use the decorator&nbsp;<em>ViewChild<\/em>&nbsp;to obtain a reference to the DOM element, by which reset the value from the&nbsp;<em>nativeElement.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can make a similar procedure for the download, but we should insert a further requisite: we want to download the file, update the progress and supply the downloaded file to a user with no more interaction.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The markup of the Download component is very simple:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;button\n\u00a0&#x5B;disabled]=&quot;disabled&quot;\n\u00a0class=&quot;button download&quot;\n\u00a0&#x5B;ngClass]=&quot;{&#039;disabled&#039;: disabled}&quot;\n\u00a0(click)=&quot;download()&quot;&gt;download&lt;\/button&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The component logic&nbsp;is very similar to that of the upload, but, as we know, once the download is terminated, we want to supply the&nbsp;file to user immediately.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nimport { Component, Input, Output, EventEmitter } from &#039;@angular\/core&#039;;\nimport { HttpEventType } from &#039;@angular\/common\/http&#039;;\nimport { UploadDownloadService } from &#039;src\/app\/services\/upload-download.service&#039;;\nimport { ProgressStatus, ProgressStatusEnum } from &#039;src\/app\/models\/progress-status.model&#039;;\n\u00a0\n@Component({\n\u00a0\u00a0selector: &#039;app-download&#039;,\n\u00a0\u00a0templateUrl: &#039;download.component.html&#039;\n})\n\u00a0\nexport class DownloadComponent {\n\u00a0\u00a0@Input() public disabled: boolean;\n\u00a0\u00a0@Input() public fileName: string;\n\u00a0\u00a0@Output() public downloadStatus: EventEmitter&lt;progressstatus&gt;;\n\u00a0\n\u00a0\u00a0constructor(private service: UploadDownloadService) {\n\u00a0\u00a0\u00a0\u00a0this.downloadStatus = new EventEmitter&lt;progressstatus&gt;();\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public download() {\n\u00a0\u00a0\u00a0\u00a0this.downloadStatus.emit( {status: ProgressStatusEnum.START});\n\u00a0\u00a0\u00a0\u00a0this.service.downloadFile(this.fileName).subscribe(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0switch (data.type) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case HttpEventType.DownloadProgress:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.downloadStatus.emit( {status: ProgressStatusEnum.IN_PROGRESS, percentage: Math.round((data.loaded \/ data.total) * 100)});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case HttpEventType.Response:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.downloadStatus.emit( {status: ProgressStatusEnum.COMPLETE});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const downloadedFile = new Blob(&#x5B;data.body], { type: data.body.type });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const a = document.createElement(&#039;a&#039;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.setAttribute(&#039;style&#039;, &#039;display:none;&#039;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0document.body.appendChild(a);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.download = this.fileName;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.href = URL.createObjectURL(downloadedFile);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.target = &#039;_blank&#039;;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a.click();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0document.body.removeChild(a);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0error =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.downloadStatus.emit( {status: ProgressStatusEnum.ERROR});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0);\n\u00a0\u00a0}\n}\n&lt;\/progressstatus&gt;&lt;\/progressstatus&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">To do that, we need to \u201cget the hands dirty\u201d and manipulate the DOM from the component. That\u2019s because the fastest way to download a file with no other interaction of the user, is to create quick an&nbsp;<em>anchor<\/em>&nbsp;element and hook to it a URL object, created from the downloaded&nbsp;<em>blob<\/em>. We can then set element&nbsp;download&#8217;s properties with the name of the file and then, clicking the element from code, we obtain a direct download also for files that a browser can open, as PDF. After that, we can delete the created&nbsp;<em>anchor<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ugly, maybe. The better thing to do would probably be to move the whole manipulation part in a guideline, but, for the purposes of our reasoning, it would not make the much difference: I leave it to you as exercise!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We use both component from the FileManager component and there you have it. HTML will be as follow:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&lt;app-upload &#x5B;disabled]=&quot;showProgress&quot; (uploadStatus)=&quot;uploadStatus($event)&quot;&gt;&lt;\/app-upload&gt;\n&lt;h2&gt;File List&lt;\/h2&gt;\n&lt;p *ngIf=&quot;showProgress&quot;&gt; progress &lt;strong&gt;{{percentage}}%&lt;\/strong&gt;&lt;\/p&gt;\n&lt;hr&gt;\n&lt;div class=&quot;container&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ul&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;li *ngFor=&quot;let file of files&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;a&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{{file}}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;app-download &#x5B;disabled]=&quot;showProgress&quot; &#x5B;fileName]=&quot;file&quot; (downloadStatus)=&quot;downloadStatus($event)&quot;&gt;&lt;\/app-download&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/a&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/li&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/ul&gt;\n&lt;\/div&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The component logic will limit itself to recover the list of available files and to show the upload and download status, based on events received from sons components:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nimport { Component, OnInit } from &#039;@angular\/core&#039;;\nimport { UploadDownloadService } from &#039;src\/app\/services\/upload-download.service&#039;;\nimport { ProgressStatusEnum, ProgressStatus } from &#039;src\/app\/models\/progress-status.model&#039;;\n\u00a0\n@Component({\n\u00a0\u00a0selector: &#039;app-filemanager&#039;,\n\u00a0\u00a0templateUrl: &#039;.\/file-manager.component.html&#039;\n})\nexport class FileManagerComponent implements OnInit {\n\u00a0\n\u00a0\u00a0public files: string&#x5B;];\n\u00a0\u00a0public fileInDownload: string;\n\u00a0\u00a0public percentage: number;\n\u00a0\u00a0public showProgress: boolean;\n\u00a0\u00a0public showDownloadError: boolean;\n\u00a0\u00a0public showUploadError: boolean;\n\u00a0\n\u00a0\u00a0constructor(private service: UploadDownloadService) { }\n\u00a0\n\u00a0\u00a0ngOnInit() {\n\u00a0\u00a0\u00a0\u00a0this.getFiles();\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0private getFiles() {\n\u00a0\u00a0\u00a0\u00a0this.service.getFiles().subscribe(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.files = data;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0);\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public downloadStatus(event: ProgressStatus) {\n\u00a0\u00a0\u00a0\u00a0switch (event.status) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.START:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showDownloadError = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.IN_PROGRESS:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.percentage = event.percentage;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.COMPLETE:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.ERROR:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showDownloadError = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0public uploadStatus(event: ProgressStatus) {\n\u00a0\u00a0\u00a0\u00a0switch (event.status) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.START:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showUploadError = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.IN_PROGRESS:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.percentage = event.percentage;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.COMPLETE:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.getFiles();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case ProgressStatusEnum.ERROR:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showProgress = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.showUploadError = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The final result is the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"984\" height=\"768\" data-attachment-id=\"29188\" data-permalink=\"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/attachment\/759bfc10-b393-4d39-b9db-b12dbfb80681-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681.png?fit=984%2C768&amp;ssl=1\" data-orig-size=\"984,768\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"759bfc10-b393-4d39-b9db-b12dbfb80681\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681.png?fit=984%2C768&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681.png?resize=984%2C768&#038;ssl=1\" alt=\"\" class=\"wp-image-29188\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681.png 984w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681-980x765.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/759bfc10-b393-4d39-b9db-b12dbfb80681-480x375.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 984px, 100vw\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"987\" height=\"768\" data-attachment-id=\"29190\" data-permalink=\"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/attachment\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c.png?fit=987%2C768&amp;ssl=1\" data-orig-size=\"987,768\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8d8ca34c-475f-4a0f-888d-5fefcbeca77c\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c.png?fit=987%2C768&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c.png?resize=987%2C768&#038;ssl=1\" alt=\"\" class=\"wp-image-29190\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c.png 987w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c-980x763.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8d8ca34c-475f-4a0f-888d-5fefcbeca77c-480x373.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 987px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">You can download source code from my GitHub at below address:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/AARNOLD87\/down-up-load-with-angular\">https:\/\/github.com\/AARNOLD87\/down-up-load-with-angular<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See you next!Alla prossima!<\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>How to upload and download files with an Angular front-end and an Asp.Net Core back-end<\/p>\n","protected":false},"author":196716250,"featured_media":29180,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_wpcom_ai_launchpad_first_post":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637524],"tags":[688637390,688637416,688637392],"class_list":["post-29193","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-en","tag-angular-en","tag-asp-net-core-en","tag-web-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Uploading and Downloading files with Angular and Asp.Net Core - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Uploading and Downloading files with Angular and Asp.Net Core - Blexin\" \/>\n<meta property=\"og:description\" content=\"How to upload and download files with an Angular front-end and an Asp.Net Core back-end\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2019-01-22T23:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-20T17:27:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Adolfo Arnold\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Adolfo Arnold\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/\"},\"author\":{\"name\":\"Adolfo Arnold\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\"},\"headline\":\"Uploading and Downloading files with Angular and Asp.Net Core\",\"datePublished\":\"2019-01-22T23:00:00+00:00\",\"dateModified\":\"2021-05-20T17:27:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/\"},\"wordCount\":892,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"Angular\",\"Asp.net core\",\"Web\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/\",\"name\":\"Uploading and Downloading files with Angular and Asp.Net Core - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2019-01-22T23:00:00+00:00\",\"dateModified\":\"2021-05-20T17:27:42+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/blog-en\\\/uploading-and-downloading-files-with-angular-and-asp-net-core\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Uploading and Downloading files with Angular and Asp.Net Core\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/en\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/en\\\/#\\\/schema\\\/person\\\/0de430b61c8a48b0e9d81308817c1517\",\"name\":\"Adolfo Arnold\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g\",\"caption\":\"Adolfo Arnold\"},\"url\":\"https:\\\/\\\/blexin.com\\\/en\\\/author\\\/adolfo-arnoldblexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Uploading and Downloading files with Angular and Asp.Net Core - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/","og_locale":"en_US","og_type":"article","og_title":"Uploading and Downloading files with Angular and Asp.Net Core - Blexin","og_description":"How to upload and download files with an Angular front-end and an Asp.Net Core back-end","og_url":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/","og_site_name":"Blexin","article_published_time":"2019-01-22T23:00:00+00:00","article_modified_time":"2021-05-20T17:27:42+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Adolfo Arnold","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Adolfo Arnold","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/"},"author":{"name":"Adolfo Arnold","@id":"https:\/\/blexin.com\/en\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517"},"headline":"Uploading and Downloading files with Angular and Asp.Net Core","datePublished":"2019-01-22T23:00:00+00:00","dateModified":"2021-05-20T17:27:42+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/"},"wordCount":892,"image":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","keywords":["Angular","Asp.net core","Web"],"articleSection":["Blog"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/","url":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/","name":"Uploading and Downloading files with Angular and Asp.Net Core - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","datePublished":"2019-01-22T23:00:00+00:00","dateModified":"2021-05-20T17:27:42+00:00","author":{"@id":"https:\/\/blexin.com\/en\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517"},"breadcrumb":{"@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/en\/blog-en\/uploading-and-downloading-files-with-angular-and-asp-net-core\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/en\/"},{"@type":"ListItem","position":2,"name":"Uploading and Downloading files with Angular and Asp.Net Core"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/en\/#website","url":"https:\/\/blexin.com\/en\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blexin.com\/en\/#\/schema\/person\/0de430b61c8a48b0e9d81308817c1517","name":"Adolfo Arnold","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ff2a87b54d0f130d7452164533199af05ef16dbd08b9241729946cea0eec7cca?s=96&d=identicon&r=g","caption":"Adolfo Arnold"},"url":"https:\/\/blexin.com\/en\/author\/adolfo-arnoldblexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/fc2a2f4b-08b6-41d8-9d20-62d7bb3ad98b.png?fit=1024%2C608&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-7AR","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/posts\/29193","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/users\/196716250"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/comments?post=29193"}],"version-history":[{"count":4,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/posts\/29193\/revisions"}],"predecessor-version":[{"id":32015,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/posts\/29193\/revisions\/32015"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/media\/29180"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/media?parent=29193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/categories?post=29193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/en\/wp-json\/wp\/v2\/tags?post=29193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}