Încărcarea și descărcarea fișierelor în angular 4 typescript (Programare, Angular, Typescript, Asp.Net Core Webapi)

Victor Athoti. a intrebat.

Cum pot descărca (.exe fișier care se află în calea rădăcinii) și Upload un fișier din Angular 4?
Sunt nou în Angular4 și typescript și .NET Core Web API.

Am căutat pe Google pentru acest lucru, dar nu am putut găsi soluția.

Iată câteva întrebări similare pe care le-am găsit:

  • Încărcarea unui fișier în controler folosind typescript

  • Returnarea fișierului binar de la controler în ASP.NET Web API

Comentarii

  • încercați cu funcția ResponseContentType.Blob din typescript –  > Por achraf akrouti.
7 răspunsuri
MoMo

Aș dori să adaug o actualizare Angular 4.3/5/6/6/7/8 pentru acest lucru, în special vis-a-vis de HttpClient simplificat. Absența lui „Content-Type” este deosebit de importantă, deoarece Angular construiește automat Content-Type (există o propensiune de a adăuga Content-Type=undefined. Nu o faceți, deoarece va crea probleme în diverse circumstanțe și, probabil, nici nu este o bună practică). Odată ce nu există un Content-Type, browserul va adăuga automat „multipart/form-data” și parametrii asociați. Notă, backend-ul aici este Spring Boot, deși nu ar trebui să conteze.

Iată un pseudocod – vă rog să scuzați degetele mari. Sper să vă fie de ajutor:

MyFileUploadComponent(.html):

...
<input type="file" (change)=fileEvent($event)...>

MyFileUploadComponent(.ts) apelează MyFileUploadService(.ts) la fileEvent:

...
public fileEvent($event) {
   const fileSelected: File = $event.target.files[0];
   this.myFileUploadService.uploadFile(fileSelected)
   .subscribe( (response) => {
      console.log('set any success actions...');
      return response;
    },
     (error) => {
       console.log('set any error actions...');
     });
}

MyFileUploadService.ts:

...
public uploadFile(fileToUpload: File) {
  const _formData = new FormData();
  _formData.append('file', fileToUpload, fileToUpload.name);   
  return<any>post(UrlFileUpload, _formData); 
  //note: no HttpHeaders passed as 3rd param to POST!
  //So no Content-Type constructed manually.
  //Angular 4.x-6.x does it automatically.
}
  

Comentarii

  • Acest răspuns mi s-a părut cel mai bun mod simplu de a îndeplini această sarcină. –  > Por Carlos Mayoral.
  • Bună MoMo mulțumesc pentru soluție, _formData afișând ca obiect gol. ca {}. Vă rog să-mi sugerați cum să trimit fișierul pe server. –  > Por YYY.
  • return<any>post() ? Într-adevăr? –  > Por TintinSansYeux.
Mohnish Karhade

Pentru încărcarea fișierelor, putem posta datele sub forma multipart/form-data. Pentru aceasta, trebuie să folosim clasa FormData. Iată un exemplu.

Template:

<form #yourForm="ngForm" (ngSubmit)="onSubmit()">
      <input type="text" [(ngModel)]="Name" name="Name"/>
      <input type="file" #fileupload [(ngModel)]="myFile" name="myFile" (change)="fileChange(fileupload.files)"/>
      <button type="submit">Submit</button>
</form>

Component:

import { Http, Response, Headers, RequestOptions } from '@angular/http';
/* When we select file */
Name:string; 
myFile:File; /* property of File type */
fileChange(files: any){
    console.log(files);

    this.myFile = files[0].nativeElement;
}

/* Now send your form using FormData */
onSubmit(): void {
    let _formData = new FormData();
    _formData.append("Name", this.Name);
    _formData.append("MyFile", this.myFile);
    let body = this._formData;
    let headers = new Headers();
    let options = new Options({
        headers: headers
    });
    this._http.post("http://example/api/YourAction", body, options)
      .map((response:Response) => <string>response.json())
      .subscribe((data) => this.message = data);
}

Pentru API pentru încărcarea fișierelor, consultați acest lucru:
https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2

Comentarii

  • Primesc o eroare în this.myFile = files[0]; ca Uncaught (în promisiune): InvalidStateError: Nu s-a reușit să setați proprietatea ‘value’ pe ‘HTMLLInputElement’: Acest element de intrare acceptă un nume de fișier, care poate fi setat numai prin programare la un șir de caractere gol. –  > Por Ajoe.
  • Magic! Folosiți Headers() și Options(). De unde sunt importate? Din Angular? De altundeva? Dacă din Angular, de unde din Angular? Aveți grijă să dați un răspuns complet. Geesh. –  > Por KhoPhi.
Daniel Charles Mwangila

foarte simplu component.html va arăta ca

<div class="form-group col-md-6" style="margin-left:50%;margin-top:-8%" >
    <input type="file" value="upload" accept=".jpg" (change)=fileUploader($event)>
</div>

în timp ce în fișierul ts, va arăta astfel

public fileUploader(event) {
    const elem = event.target;
    if (elem.files.length > 0) {
        console.log(elem.files[0]);
    }
    // ...
}

Praveen Gubbala
<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
    Select image to upload:
    <input type="file" name="avatar" id="fileToUpload" formControlName="file1" (change)="fileEvent($event)">
    <input type="submit" value="Upload Image" name="submit">
</form>
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
@Component({
  selector: 'app-praveen',
  templateUrl: './praveen.component.html',
  styleUrls: ['./praveen.component.css']
})
export class PraveenComponent implements OnInit {

  constructor(private httpClient:HttpClient) { }
    uploadForm = new FormGroup ({
        file1: new FormControl()
    });
    filedata:any;
    fileEvent(e){
        this.filedata=e.target.files[0];
        console.log(e);
    }
    onSubmit() {
        let formdata = new FormData();
        console.log(this.uploadForm)
        formdata.append("avatar",this.filedata);
        this.httpClient
        .post<any>("http://localhost:3040/uploading",formdata)
        .subscribe((res)=>{console.log(res});
    }
  ngOnInit() {
  }

}

Comentarii

  • M-a ajutat 🙂 –  > Por Ajay Malhotra.
achraf akrouti

pentru a descărca fișiere cu angular încercați cu acest lucru, funcționează`

download(row) {
    return this.Http
      .get(file_path , {
        responseType: ResponseContentType.Blob,
      })
      .map(res => {
        return {
          filename: row.name,
          data: res.blob()
        };
      })
      .subscribe(res => {
        let url = window.URL.createObjectURL(res.data);
        let a = document.createElement('a');
        document.body.appendChild(a);
        a.setAttribute('style', 'display: none');
        a.href = url;
        a.download = res.filename;
        a.click();
        window.URL.revokeObjectURL(url);
        a.remove();
      });
  }

`

Prasad Shigwan

Vă rugăm să vă referiți la codul de mai jos pentru codul de încărcare a fișierelor.html:

<div class="col-md-6">
     <label class="control-heading">Select File</label>
     <input type="file" [multiple]="multiple" #fileInput (change)="selectFile($event)">
     <input type="button" style="margin-top: 15px;" [disabled]="!isUploadEditable" class="data-entry-button btn-pink" (click)="uploadFile()" value="Upload" title="{{globalService.generateTooltip('upload attachment','Click to upload document.')}}" data-html="true" data-toggle="tooltip" data-placement="bottom" />
</div>

Codul componentei:

selectFile(event: any) {
    this.selectedFiles = event.target.files;
}

uploadFile() {
    this.currentFileUpload = this.selectedFiles.item(0);
    this.globalService.pushFileToStorage(this.currentFileUpload).subscribe(event => {
        if (event instanceof HttpResponse) {
            this.loadDocumentInfo();
            this.showNotification('Upload Attachment', 'File Uploaded Successfully', 'success');
            this.myInputVariable.nativeElement.value = "";
        }
    });
    this.selectedFiles = undefined;
}

Codul serviciului global:

pushFileToStorage(file: File): Observable<HttpEvent<{}>> {
    const formdata: FormData = new FormData();
    formdata.append('file', file);
    formdata.append('documentVersionId', this.documentVersionId.toString());
    formdata.append('levelId', this.levelId);
    formdata.append('levelKey', this.levelKey);
    formdata.append('LoggedInUser', this.loggedInUser);
    const req = new HttpRequest('POST', this.urlService.CMMService + '/CMMService-service/UploadFileAsAttachment', formdata, {
        reportProgress: true,
        responseType: 'text'
    }
    );
    return this.http.request(req);
}

Pentru a descărca un fișier cu numele și calea de acces:

apelați funcția DownloadFile din html cu numele fișierului și calea fișierului ca parametri.

cod componentă:

DownloadFile(filePath: string, filename: string) {
    this.globalService.DownloadFile(filePath).subscribe(res => {
        //console.log('start download:', res);
        var url = window.URL.createObjectURL(res);
        var a = document.createElement('a');
        document.body.appendChild(a);
        a.setAttribute('style', 'display: none');
        a.href = url;
        res.filename = filename;
        a.download = res.filename;
        a.click();
        window.URL.revokeObjectURL(url);
        a.remove(); // remove the element
    }, error => {
        console.log('download error:', JSON.stringify(error));
    }, () => {
        console.log('Completed file download.')
    });
}

Cod de serviciu global pentru a descărca un fișier:

public DownloadFile(filePath: string): Observable<any> {
   return this.http
        .get(this.urlService.CMMService + '/CMMService-service/DownloadFile?filePath=' + filePath, {
            responseType: 'blob'
        });
}

pe partea serverului, vă rugăm să utilizați codul de mai jos:

[HttpGet]
        [ODataRoute("DownloadFile")]
        public HttpResponseMessage DownloadFile(string filePath)
        {
            var fileData = CommonDomain.DownloadFileFromS3(filePath);
            var dataStream = new MemoryStream(fileData.ByteArray);
            HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
            httpResponseMessage.Content = new StreamContent(dataStream);
            httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileData.FileName;
            httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            httpResponseMessage.Content.Headers.Add("x-filename", fileData.FileName);
            return httpResponseMessage;
        }

Vă rog să mă anunțați dacă vă mai confruntați cu vreo problemă.

Swati

Descărcați orice fișier de pe server utilizând Angular 8+ și versiunea ASP.NET CORE 2+.

Implementarea controlerului pentru a descărca fișierul:

    [HttpGet]
        [Route("download")]
        public async Task Download([FromQuery] string file) {
            var uploads = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
            var filePath = Path.Combine(uploads, file);
            if (!System.IO.File.Exists(filePath))
                return NotFound();
    
            var memory = new MemoryStream();
            using (var stream = new FileStream(filePath, FileMode.Open))
            {
                await stream.CopyToAsync(memory);
            }
            memory.Position = 0;
    
            return File(memory, GetContentType(filePath), file); 
        }

Creați serviciul angular

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http';
    import { Observable } from 'rxjs';
     
    @Injectable()
    export class DownloadService {
      private baseApiUrl: string;
      private apiDownloadUrl: string;
      private apiUploadUrl: string;
      private apiFileUrl: string;
     
      constructor(private httpClient: HttpClient) {
        this.baseApiUrl = 'http://localhost:5001/api/';
        this.apiDownloadUrl = this.baseApiUrl + 'download';
        this.apiUploadUrl = this.baseApiUrl + 'upload';
        this.apiFileUrl = this.baseApiUrl + 'files';
      }
     
      public downloadFile(file: string): Observable> {
        return this.httpClient.request(new HttpRequest(
          'GET',
          `${this.apiDownloadUrl}?file=${file}`,
          null,
          {
            reportProgress: true,
            responseType: 'blob'
          }));
      }
     }

Creați un model în angular

    export interface ProgressStatus {
      status: ProgressStatusEnum;
      percentage?: number;
    }
     
    export enum ProgressStatusEnum {
      START, COMPLETE, IN_PROGRESS, ERROR
    }

Creați o componentă pentru a descărca un fișier

    <button
     [disabled]="disabled"
     class="button download"
     [ngClass]="{'disabled': disabled}"
     (click)="download()">download

Creați o componentă copil pentru a descărca un fișier. Următorul cod în fișierul typescript:

    import { Component, Input, Output, EventEmitter } from '@angular/core';
    import { HttpEventType } from '@angular/common/http';
    import { UploadDownloadService } from 'src/app/services/upload-download.service';
    import { ProgressStatus, ProgressStatusEnum } from 'src/app/models/progress-status.model';
     
    @Component({
      selector: 'app-download',
      templateUrl: 'download.component.html'
    })
     
    export class DownloadComponent {
      @Input() public disabled: boolean;
      @Input() public fileName: string;
      @Output() public downloadStatus: EventEmitter;
     
      constructor(private service: UploadDownloadService) {
        this.downloadStatus = new EventEmitter();
      }
     
      public download() {
        this.downloadStatus.emit( {status: ProgressStatusEnum.START});
        this.service.downloadFile(this.fileName).subscribe(
          data => {
            switch (data.type) {
              case HttpEventType.DownloadProgress:
                this.downloadStatus.emit( {status: ProgressStatusEnum.IN_PROGRESS, percentage: Math.round((data.loaded / data.total) * 100)});
                break;
              case HttpEventType.Response:
                this.downloadStatus.emit( {status: ProgressStatusEnum.COMPLETE});
                const downloadedFile = new Blob([data.body], { type: data.body.type });
                const a = document.createElement('a');
                a.setAttribute('style', 'display:none;');
                document.body.appendChild(a);
                a.download = this.fileName;
                a.href = URL.createObjectURL(downloadedFile);
                a.target = '_blank';
                a.click();
                document.body.removeChild(a);
                break;
            }
          },
          error => {
            this.downloadStatus.emit( {status: ProgressStatusEnum.ERROR});
          }
        );
      }
    }

Adăugați următoarea implementare în componenta părinte:

    <app-download [disabled]="showProgress" [fileName]="file" (downloadStatus)="downloadStatus($event)">
    <p *ngIf="showProgress"> progress <strong>{{percentage}}%</strong>

Adăugați următoarea implementare în componenta typescript părinte:

    import { Component, OnInit } from '@angular/core';
    import { UploadDownloadService } from 'src/app/services/upload-download.service';
    import { ProgressStatusEnum, ProgressStatus } from 'src/app/models/progress-status.model';
     
    @Component({
      selector: 'app-filemanager',
      templateUrl: './file-manager.component.html'
    })
    export class FileManagerComponent implements OnInit {
     
      public files: string[];
      public fileInDownload: string;
      public percentage: number;
      public showProgress: boolean;
      public showDownloadError: boolean;
      public showUploadError: boolean;
     
      constructor(private service: UploadDownloadService) { }
     
      ngOnInit() {
        this.getFiles();
      }
     
      private getFiles() {
        this.service.getFiles().subscribe(
          data => {
            this.files = data;
          }
        );
      }
     
      public downloadStatus(event: ProgressStatus) {
        switch (event.status) {
          case ProgressStatusEnum.START:
            this.showDownloadError = false;
            break;
          case ProgressStatusEnum.IN_PROGRESS:
            this.showProgress = true;
            this.percentage = event.percentage;
            break;
          case ProgressStatusEnum.COMPLETE:
            this.showProgress = false;
            break;
          case ProgressStatusEnum.ERROR:
            this.showProgress = false;
            this.showDownloadError = true;
            break;
        }
      }
    }

FĂCUT!