文件上传和下载角4打字稿

时间:2017-07-18 08:04:21

标签: angular typescript asp.net-core-webapi

如何下​​载(根路径中的.exe文件)和从Angular 4上传文件?
我是Angular4和打字稿以及.NET Core Web API的新手。我用谷歌搜索但找不到解决方案。

以下是我发现的一些类似问题:

7 个答案:

答案 0 :(得分:21)

我想为此添加一个Angular 4.3 / 5/6更新,尤其是与简化的HttpClient相比。由于Angular会自动构建Content-Type(因此存在添加Content-Type = undefined的倾向,因此不存在'Content-Type'特别重要。不要,因为它会在各种情况下产生问题,也许不会好的做法)。一旦没有Content-Type,浏览器将自动添加'multipart / form-data'和相关参数。注意,这里的后端是Spring Boot,虽然它没关系。

这是一些伪代码 - 请原谅phat手指。希望这会有所帮助:

<强> MyFileUploadComponent(html的):

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

MyFileUploadComponent(.ts)在fileEvent上调用MyFileUploadService(.ts):

...
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 3d param to POST!
                                           //So no Content-Type constructed manually.
                                           //Angular 4.x-6.x does it automatically.
}

答案 1 :(得分:10)

对于上传文件,我们可以以multipart / form-data的形式发布数据。为此,我们必须使用FormData类。这是一个例子。

模板:

<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>

组件:

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

要上传API文件,请参阅:
https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2

答案 2 :(得分:1)

非常简单 component.html看起来像

<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>

在ts文件中,它看起来像

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

答案 3 :(得分:0)

<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() {
  }

}

答案 4 :(得分:0)

尝试用角度下载文件,就可以了

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

`

答案 5 :(得分:0)

请参考以下代码进行文件上传。 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>

组件代码:

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

全球服务代码:

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

要下载具有文件名和文件路径的文件:

使用文件名和文件路径作为参数从html调用DownloadFile函数。

组件代码:

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

下载文件的全球服务代码:

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

在服务器端,请使用以下代码:

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

请让我知道你们是否仍然遇到任何问题。

答案 6 :(得分:0)

使用Angular 8+和ASP.NET CORE 2+版本从服务器下载任何文件。

下载文件的控制器实现:


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

创建角度服务


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

创建角度模型


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

创建一个组件以下载文件


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

创建一个子组件以下载文件。打字稿文件中的以下代码:


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

在父组件中添加以下实现:


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

在父打字稿组件中添加以下实现:


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

完成!