Upload

Upload file by selecting or dragging.

When To Use#

Uploading is the process of publishing information (web pages, text, pictures, video, etc.) to a remote server via a web page or upload tool.

  • When you need to upload one or more files.
  • When you need to show the process of uploading.
  • When you need to upload files by dragging and dropping.

Examples

Classic mode. File selection dialog pops up when upload button is clicked.

expand codeexpand code
import { Component } from '@angular/core';

@Component({
  selector: 'nz-demo-upload-basic',
  template: `
    <nz-upload nzAction="https://jsonplaceholder.typicode.com/posts/">
      <button nz-button><i nz-icon nzType="upload"></i><span>Click to Upload</span></button>
    </nz-upload>
  `
})
export class NzDemoUploadBasicComponent {}

Use nzFileList for uploaded files when page init.

expand codeexpand code
import { Component } from '@angular/core';

@Component({
  selector: 'nz-demo-upload-file-list',
  template: `
    <nz-upload nzAction="https://jsonplaceholder.typicode.com/posts/" [nzFileList]="fileList">
      <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
    </nz-upload>
  `
})
export class NzDemoUploadFileListComponent {
  fileList = [
    {
      uid: 1,
      name: 'xxx.png',
      status: 'done',
      response: 'Server Error 500', // custom error message to show
      url: 'http://www.baidu.com/xxx.png'
    },
    {
      uid: 2,
      name: 'yyy.png',
      status: 'done',
      url: 'http://www.baidu.com/yyy.png'
    },
    {
      uid: 3,
      name: 'zzz.png',
      status: 'error',
      response: 'Server Error 500', // custom error message to show
      url: 'http://www.baidu.com/zzz.png'
    }
  ];
}

You can gain full control over filelist by configuring nzFilter. You can accomplish all kinds of customed functions. The following shows three circumstances:

1) limit the number of uploaded files.

2) read from response and show file link.

3) filter successfully uploaded files according to response from server.

expand codeexpand code
import { Component } from '@angular/core';
import { NzMessageService, UploadFile, UploadFilter } from 'ng-zorro-antd';
import { Observable, Observer } from 'rxjs';

@Component({
  selector: 'nz-demo-upload-filter',
  template: `
    <nz-upload
      nzAction="https://jsonplaceholder.typicode.com/posts/"
      [nzFileList]="fileList"
      nzMultiple
      [nzLimit]="2"
      [nzFilter]="filters"
      (nzChange)="handleChange($event)"
    >
      <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
    </nz-upload>
  `
})
export class NzDemoUploadFilterComponent {
  constructor(private msg: NzMessageService) {}

  filters: UploadFilter[] = [
    {
      name: 'type',
      fn: (fileList: UploadFile[]) => {
        const filterFiles = fileList.filter(w => ~['image/png'].indexOf(w.type));
        if (filterFiles.length !== fileList.length) {
          this.msg.error(`包含文件格式不正确,只支持 png 格式`);
          return filterFiles;
        }
        return fileList;
      }
    },
    {
      name: 'async',
      fn: (fileList: UploadFile[]) => {
        return new Observable((observer: Observer<UploadFile[]>) => {
          // doing
          observer.next(fileList);
          observer.complete();
        });
      }
    }
  ];

  fileList = [
    {
      uid: -1,
      name: 'xxx.png',
      status: 'done',
      url: 'http://www.baidu.com/xxx.png'
    }
  ];

  // tslint:disable-next-line:no-any
  handleChange(info: any): void {
    const fileList = info.fileList;
    // 2. read from response and show file link
    if (info.file.response) {
      info.file.url = info.file.response.url;
    }
    // 3. filter successfully uploaded files according to response from server
    // tslint:disable-next-line:no-any
    this.fileList = fileList.filter((item: any) => {
      if (item.response) {
        return item.response.status === 'success';
      }
      return true;
    });
  }
}

You can select and upload a whole directory.

expand codeexpand code
import { Component } from '@angular/core';

@Component({
  selector: 'nz-demo-upload-directory',
  template: `
    <nz-upload nzAction="https://jsonplaceholder.typicode.com/posts/" nzDirectory>
      <button nz-button><i nz-icon nzType="upload"></i> Upload Directory</button>
    </nz-upload>
  `
})
export class NzDemoUploadDirectoryComponent {}

If uploaded file is a picture, the thumbnail can be shown. IE8/9 do not support local thumbnail show. Please use thumbUrl instead.

expand codeexpand code
import { Component } from '@angular/core';

@Component({
  selector: 'nz-demo-upload-picture-style',
  template: `
    <div class="clearfix">
      <nz-upload nzAction="https://jsonplaceholder.typicode.com/posts/" nzListType="picture" [(nzFileList)]="fileList1">
        <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
      </nz-upload>
    </div>
    <br /><br />
    <div class="clearfix">
      <nz-upload
        class="upload-list-inline"
        nzAction="https://jsonplaceholder.typicode.com/posts/"
        nzListType="picture"
        [(nzFileList)]="fileList2"
      >
        <button nz-button>
          <span><i nz-icon nzType="upload"></i> Upload</span>
        </button>
      </nz-upload>
    </div>
  `,
  styles: [
    `
      :host ::ng-deep .upload-list-inline .ant-upload-list-item {
        float: left;
        width: 200px;
        margin-right: 8px;
      }
    `
  ]
})
export class NzDemoUploadPictureStyleComponent {
  defaultFileList = [
    {
      uid: -1,
      name: 'xxx.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
      thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
    },
    {
      uid: -2,
      name: 'yyy.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
      thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
    }
  ];

  fileList1 = [...this.defaultFileList];
  fileList2 = [...this.defaultFileList];
}
Upload

Click to upload user's avatar, and validate size and format of picture with nzBeforeUpload.

The return value of function nzBeforeUpload can be a Observable to check asynchronously.

expand codeexpand code
import { Component } from '@angular/core';
import { NzMessageService, UploadFile } from 'ng-zorro-antd';
import { Observable, Observer } from 'rxjs';

@Component({
  selector: 'nz-demo-upload-avatar',
  template: `
    <nz-upload
      class="avatar-uploader"
      nzAction="https://jsonplaceholder.typicode.com/posts/"
      nzName="avatar"
      nzListType="picture-card"
      [nzShowUploadList]="false"
      [nzBeforeUpload]="beforeUpload"
      (nzChange)="handleChange($event)"
    >
      <ng-container *ngIf="!avatarUrl">
        <i class="upload-icon" nz-icon [nzType]="loading ? 'loading' : 'plus'"></i>
        <div class="ant-upload-text">Upload</div>
      </ng-container>
      <img *ngIf="avatarUrl" [src]="avatarUrl" class="avatar" />
    </nz-upload>
  `,
  styles: [
    `
      .avatar {
        width: 128px;
        height: 128px;
      }
      .upload-icon {
        font-size: 32px;
        color: #999;
      }
      .ant-upload-text {
        margin-top: 8px;
        color: #666;
      }
    `
  ]
})
export class NzDemoUploadAvatarComponent {
  loading = false;
  avatarUrl: string;

  constructor(private msg: NzMessageService) {}

  beforeUpload = (file: File) => {
    return new Observable((observer: Observer<boolean>) => {
      const isJPG = file.type === 'image/jpeg';
      if (!isJPG) {
        this.msg.error('You can only upload JPG file!');
        observer.complete();
        return;
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.msg.error('Image must smaller than 2MB!');
        observer.complete();
        return;
      }
      // check height
      this.checkImageDimension(file).then(dimensionRes => {
        if (!dimensionRes) {
          this.msg.error('Image only 300x300 above');
          observer.complete();
          return;
        }

        observer.next(isJPG && isLt2M && dimensionRes);
        observer.complete();
      });
    });
  };

  private getBase64(img: File, callback: (img: string) => void): void {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result!.toString()));
    reader.readAsDataURL(img);
  }

  private checkImageDimension(file: File): Promise<boolean> {
    return new Promise(resolve => {
      const img = new Image(); // create image
      img.src = window.URL.createObjectURL(file);
      img.onload = () => {
        const width = img.naturalWidth;
        const height = img.naturalHeight;
        window.URL.revokeObjectURL(img.src!);
        resolve(width === height && width >= 300);
      };
    });
  }

  handleChange(info: { file: UploadFile }): void {
    switch (info.file.status) {
      case 'uploading':
        this.loading = true;
        break;
      case 'done':
        // Get this url from response in real world.
        this.getBase64(info.file!.originFileObj!, (img: string) => {
          this.loading = false;
          this.avatarUrl = img;
        });
        break;
      case 'error':
        this.msg.error('Network error');
        this.loading = false;
        break;
    }
  }
}
Upload

After users upload picture, the thumbnail will be shown in list. The upload button will disappear when count meets limitation.

expand codeexpand code
import { Component } from '@angular/core';
import { UploadFile } from 'ng-zorro-antd';

@Component({
  selector: 'nz-demo-upload-picture-card',
  template: `
    <div class="clearfix">
      <nz-upload
        nzAction="https://jsonplaceholder.typicode.com/posts/"
        nzListType="picture-card"
        [(nzFileList)]="fileList"
        [nzShowButton]="fileList.length < 3"
        [nzShowUploadList]="showUploadList"
        [nzPreview]="handlePreview"
      >
        <i nz-icon nzType="plus"></i>
        <div class="ant-upload-text">Upload</div>
      </nz-upload>
      <nz-modal
        [nzVisible]="previewVisible"
        [nzContent]="modalContent"
        [nzFooter]="null"
        (nzOnCancel)="previewVisible = false"
      >
        <ng-template #modalContent>
          <img [src]="previewImage" [ngStyle]="{ width: '100%' }" />
        </ng-template>
      </nz-modal>
    </div>
  `,
  styles: [
    `
      i[nz-icon] {
        font-size: 32px;
        color: #999;
      }
      .ant-upload-text {
        margin-top: 8px;
        color: #666;
      }
    `
  ]
})
export class NzDemoUploadPictureCardComponent {
  showUploadList = {
    showPreviewIcon: true,
    showRemoveIcon: true,
    hidePreviewIconInNonImage: true
  };
  fileList = [
    {
      uid: -1,
      name: 'xxx.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
    }
  ];
  previewImage: string | undefined = '';
  previewVisible = false;

  constructor() {}

  handlePreview = (file: UploadFile) => {
    this.previewImage = file.url || file.thumbUrl;
    this.previewVisible = true;
  };
}

Click or drag file to this area to upload

Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files

You can drag files to a specific area, to upload. Alternatively, you can also upload by selecting.

We can upload serveral files at once in modern browsers by giving the input the nzMultiple attribute.

expand codeexpand code
import { Component } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd';

@Component({
  selector: 'nz-demo-upload-drag',
  template: `
    <nz-upload
      nzType="drag"
      [nzMultiple]="true"
      [nzLimit]="2"
      nzAction="https://jsonplaceholder.typicode.com/posts/"
      (nzChange)="handleChange($event)"
    >
      <p class="ant-upload-drag-icon">
        <i nz-icon nzType="inbox"></i>
      </p>
      <p class="ant-upload-text">Click or drag file to this area to upload</p>
      <p class="ant-upload-hint">
        Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files
      </p>
    </nz-upload>
  `
})
export class NzDemoUploadDragComponent {
  constructor(private msg: NzMessageService) {}
  // tslint:disable-next-line:no-any
  handleChange({ file, fileList }: { [key: string]: any }): void {
    const status = file.status;
    if (status !== 'uploading') {
      console.log(file, fileList);
    }
    if (status === 'done') {
      this.msg.success(`${file.name} file uploaded successfully.`);
    } else if (status === 'error') {
      this.msg.error(`${file.name} file upload failed.`);
    }
  }
}

Upload files manually after nzBeforeUpload returns false.

expand codeexpand code
import { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http';
import { Component } from '@angular/core';
import { NzMessageService, UploadFile } from 'ng-zorro-antd';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'nz-demo-upload-manually',
  template: `
    <nz-upload [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload">
      <button nz-button><i nz-icon nzType="upload"></i><span>Select File</span></button>
    </nz-upload>
    <button
      nz-button
      [nzType]="'primary'"
      [nzLoading]="uploading"
      (click)="handleUpload()"
      [disabled]="fileList.length == 0"
      style="margin-top: 16px"
    >
      {{ uploading ? 'Uploading' : 'Start Upload' }}
    </button>
  `
})
export class NzDemoUploadManuallyComponent {
  uploading = false;
  fileList: UploadFile[] = [];

  constructor(private http: HttpClient, private msg: NzMessageService) {}

  beforeUpload = (file: UploadFile): boolean => {
    this.fileList = this.fileList.concat(file);
    return false;
  };

  handleUpload(): void {
    const formData = new FormData();
    // tslint:disable-next-line:no-any
    this.fileList.forEach((file: any) => {
      formData.append('files[]', file);
    });
    this.uploading = true;
    // You can use any AJAX library you like
    const req = new HttpRequest('POST', 'https://jsonplaceholder.typicode.com/posts/', formData, {
      // reportProgress: true
    });
    this.http
      .request(req)
      .pipe(filter(e => e instanceof HttpResponse))
      .subscribe(
        () => {
          this.uploading = false;
          this.fileList = [];
          this.msg.success('upload successfully.');
        },
        () => {
          this.uploading = false;
          this.msg.error('upload failed.');
        }
      );
  }
}

Use nzCustomRequest override for the default xhr behavior.

expand codeexpand code
import { HttpClient, HttpEvent, HttpEventType, HttpRequest, HttpResponse } from '@angular/common/http';
import { Component } from '@angular/core';
import { UploadXHRArgs } from 'ng-zorro-antd';
import { forkJoin } from 'rxjs';

@Component({
  selector: 'nz-demo-upload-custom-request',
  template: `
    <nz-upload nzAction="https://jsonplaceholder.typicode.com/posts/" [nzCustomRequest]="customReq">
      <button nz-button><i nz-icon nzType="upload"></i><span>Click to Upload</span></button>
    </nz-upload>
  `
})
export class NzDemoUploadCustomRequestComponent {
  constructor(private http: HttpClient) {}

  customReq = (item: UploadXHRArgs) => {
    // 构建一个 FormData 对象,用于存储文件或其他参数
    const formData = new FormData();
    // tslint:disable-next-line:no-any
    formData.append('file', item.file as any);
    formData.append('id', '1000');
    const req = new HttpRequest('POST', item.action!, formData, {
      reportProgress: true,
      withCredentials: true
    });
    // 始终返回一个 `Subscription` 对象,nz-upload 会在适当时机自动取消订阅
    return this.http.request(req).subscribe(
      (event: HttpEvent<{}>) => {
        if (event.type === HttpEventType.UploadProgress) {
          if (event.total! > 0) {
            // tslint:disable-next-line:no-any
            (event as any).percent = (event.loaded / event.total!) * 100;
          }
          // 处理上传进度条,必须指定 `percent` 属性来表示进度
          item.onProgress!(event, item.file!);
        } else if (event instanceof HttpResponse) {
          // 处理成功
          item.onSuccess!(event.body, item.file!, event);
        }
      },
      err => {
        // 处理失败
        item.onError!(err, item.file!);
      }
    );
  };

  // 一个简单的分片上传
  customBigReq = (item: UploadXHRArgs) => {
    const size = item.file.size;
    const chunkSize = parseInt(size / 3 + '', 10);
    const maxChunk = Math.ceil(size / chunkSize);
    const reqs = Array(maxChunk)
      .fill(0)
      .map((_: {}, index: number) => {
        const start = index * chunkSize;
        let end = start + chunkSize;
        if (size - end < 0) {
          end = size;
        }
        const formData = new FormData();
        formData.append('file', item.file.slice(start, end));
        formData.append('start', start.toString());
        formData.append('end', end.toString());
        formData.append('index', index.toString());
        const req = new HttpRequest('POST', item.action!, formData, {
          withCredentials: true
        });
        return this.http.request(req);
      });
    return forkJoin(...reqs).subscribe(
      () => {
        // 处理成功
        item.onSuccess!({}, item.file!, event);
      },
      err => {
        // 处理失败
        item.onError!(err, item.file!);
      }
    );
  };
}

API#

You can consult jQuery-File-Upload about how to implement server side upload interface.

Import this Component Individually#

You can get more detail here.

import { NzUploadModule } from 'ng-zorro-antd';

nz-upload#

PropertyDescriptionTypeDefault
[nzAccept]File types that can be accepted. See input accept Attributestring-
[nzAction]Required. Uploading URLstring-
[nzDirectory]support upload whole directory (caniuse)booleanfalse
[nzBeforeUpload]Hook function which will be executed before uploading. Uploading will be stopped with false or a Observable. Warning:this function is not supported in IE9. NOTICE: Muse be use => to define the method.(file: UploadFile, fileList: UploadFile[]) => boolean|Observable<boolean>-
[nzCustomRequest]override for the default xhr behavior allowing for additional customization and ability to implement your own XMLHttpRequest. NOTICE: Muse be use => to define the method.(item) => Subscription-
[nzData]Uploading params or function which can return uploading params. NOTICE: Muse be use => to define the method.Object|((file: UploadFile) => Object)-
[nzDisabled]disable upload buttonbooleanfalse
[nzFileList]List of files, two-way data-bindingUploadFile[]-
[nzLimit]limit single upload count when nzMultiple has opened. 0 unlimitednumber0
[nzSize]limit file size (KB). 0 unlimitednumber0
[nzFileType]limit file type, e.g: image/png,image/jpeg,image/gif,image/bmpstring-
[nzFilter]Custom filter when choosed fileUploadFilter[]-
[nzHeaders]Set request headers, valid above IE10. NOTICE: Muse be use => to define the method.Object|((file: UploadFile) => Object)-
[nzListType]Built-in stylesheets, support for three types: text, picture or picture-card'text'|'picture'|'picture-card''text'
[nzMultiple]Whether to support selected multiple file. IE10+ supported. You can select multiple files with CTRL holding down while multiple is set to be truebooleanfalse
[nzName]The name of uploading filestring'file'
[nzShowUploadList]Whether to show default upload list, could be an object to specify showPreviewIcon and showRemoveIcon individuallyboolean|{ showPreviewIcon?: boolean, showRemoveIcon?: boolean }true
[nzShowButton]Show upload buttonbooleantrue
[nzWithCredentials]ajax upload with cookie sentbooleanfalse
[nzOpenFileDialogOnClick]click open file dialogbooleantrue
[nzPreview]A callback function, will be executed when file link or preview icon is clicked. NOTICE: Muse be use => to define the method.(file: UploadFile) => void-
[nzRemove]A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is false or a Observable. NOTICE: Muse be use => to define the method.(file: UploadFile) => boolean|Observable<boolean>-
(nzChange)A callback function, can be executed when uploading state is changingEventEmitter<UploadChangeParam>-

nzChange#

The function will be called when uploading is in progress, completed or failed

When uploading state change, it returns:

{
  file: { /* ... */ },
  fileList: [ /* ... */ ],
  event: { /* ... */ },
}
  1. file File object for the current operation.

    {
       uid: 'uid',      // unique identifier
       name: 'xx.png'   // file name
       status: 'done', // options:uploading, done, error, removed
       response: '{"status": "success"}', // response from server
       linkProps: '{"download": "image"}', // additional html props of file link
    }
  2. fileList current list of files

  3. event response from server, including uploading progress, supported by advanced browsers.

nzCustomRequest#

Allows for advanced customization by overriding default behavior in HttpClient. Provide your own XMLHttpRequest calls to interface with custom backend processes or interact with AWS S3 service through the aws-sdk-js package.

nzCustomRequest callback is passed an object with:

  • onProgress: (event: { percent: number }): void
  • onError: (event: Error): void
  • onSuccess: (body: Object, xhr?: Object): void
  • data: Object
  • filename: String
  • file: File
  • withCredentials: Boolean
  • action: String
  • headers: Object