一、前言
老规矩,每篇开篇之前先啰嗦一下吧。昨天刚刚把那个zip上传bug修复和新增一个上传进度条。今天在昨天的基础上提了更进步的需求,需要提供一个取消按钮,能够终止上传请求,目的是防止选择了错误的文件无法终止的情况,说到这,你们肯定会说断点续传和分片上传之类的,不过很不好意思,我上传的地方是一个动态的地址,没有后台接口支持我这么做,至少目前是这样的,据说以后会换成阿里的OSS,这个是支持断点和分片的,如果有重构的话,之后再续写了。
二、思路
- httpclient中有一个subscribe()方法,会返回一个promise对象,这个对象具有一个unsubscribe()方法,可以取消请求。
- 在类中定义一个属性缓存本次请求的promise对象
- 创建一个数组来缓存被取消请求的id属性
- 开启了
reportProgress: true
,接口会监听event,不断返回状态信息event,其包含type,loaded和total属性,通过(event.loaded/evet.total)*100
可以计算出完成度的百分比。正是会不断执行subscribe()方法,即可在这个方法里面来做请求取消。
三、简单实例
import { Component, OnInit } from '@angular/core'; import { NzUploadFile, NzUploadXHRArgs, NzUploadChangeParam,UploadFilter } from 'ng-zorro-antd/upload'; import { NzMessageService } from 'ng-zorro-antd/message'; import { MyProfileCrudService } from '../../services/my-profile-crud.service'; import { HttpRequest, HttpClient, HttpHeaders, HttpEvent, HttpEventType, HttpResponse } from '@angular/common/http'; import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'; import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'; @Component({ selector: 'app-consultation-list', templateUrl: './consultation-list.component.html', styleUrls: ['./consultation-list.component.scss'] }) export class ConsultationListComponent implements OnInit { private private canceler; constructor(private modal: NzModalService, public sanitizer: DomSanitizer, private _myProfileCrudService: MyProfileCrudService, private _http: HttpClient, private _message: NzMessageService) {} //上传文件 beforeUpload = (file: NzUploadFile): boolean => { const queryParams = { checkName: this.checkName } //获取上传文件url路径 this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => { //上传路径 const uploadUrl = data.data.body.urls.uploadUrl; this.aiCheckId = data.data.body.aiCheckId let File : any = file; //请求头 const headers = new HttpHeaders() .set('Content-Type','application/zip') //创建请求对象 const request = new HttpRequest('PUT', uploadUrl, File as File, { headers, reportProgress: true, }); //将subscribe方法的返回对象赋值给canceler this.canceler = this._http.request(request).subscribe(event => { console.log(event) }) return false; }; //取消上传请求 cancelUploadRequest(){ //取消请求 this.canceler.unsubscribe(); } }
执行cancelUploadRequest方法即可取消http请求,简单吧!目前网上基本上没有相关资料,第一份哦!
四、文件上传取消示例
1. html代码示例
<nz-modal nzWidth="383px" height="415px" [(nzOkDisabled)]="isOkDisabled" [(nzVisible)]="isUploadVisible" nzTitle="上传影像数据" (nzOnCancel)="handleCancel()" (nzOnOk)="handleClickOk()"> <div style="font-size:16px"> 名称 </div> <div> <input nz-input style=" width: 200px; height: 40px; background: #F1F1F1; border-radius: 6px; margin-top: 10px;" class="uploader-input" type="text" [(ngModel)]="checkName" placeholder="输入检测名称"/> </div> <nz-upload [(nzFileList)]="fileList" [nzMultiple]="true" nzListType="" [nzBeforeUpload]="beforeUpload" [nzFilter]="filters"> <!-- <button [(disabled)]="!checkName" style="width: 300px; height: 40px;margin-top:26px;background: #F1F1F1;" nz-button><i nz-icon nzType="upload"></i>选择zip文件</button> --> <button nz-button [(disabled)]="!checkName || isUploadDisable" style="width: 160px;height: 160px;border-radius: 6px;border-style: dotted;border-color: #858585; box-shadow: 0px 3px 8px 0px rgba(200,200,200,0.6);border-radius: 12px; margin-top: 20px;text-align:center;color:black;"> <div style="width:100%;height:100%;font-size:60px;line-height: 130px; text-align:center;color: #858585"> + <div style="font-size: 12px;margin-top: -60px;"> 选择zip文件上传 </div> </div> </button> </nz-upload> <div style="width: 240px; height:40px;margin-top:26px"> <nz-progress [(nzPercent)]="schedule" [nzStrokeColor]="{ '0%': '#B04FDD', '100%': '#B04FDD' }"></nz-progress> </div> <div *nzModalFooter> <button nz-button nzType="default" (click)="handleCancel()">取消</button> <button [(disabled)]="isOkDisabled" nz-button nzType="default" (click)="primary" style="color: #fff; background: #B04FDD; border-color: #1890ff; text-shadow: 0 -1px 0 rgb(0 0 0 / 12%); box-shadow: 0 2px 0 rgb(0 0 0 / 5%);" (click)="handleClickOk()"> 确定 </button> </div> </nz-modal>
2. js代码示例
import { Component, OnInit } from '@angular/core'; import { NzUploadFile, NzUploadXHRArgs, NzUploadChangeParam,UploadFilter } from 'ng-zorro-antd/upload'; import { NzMessageService } from 'ng-zorro-antd/message'; import { MyProfileCrudService } from '../../services/my-profile-crud.service'; import { HttpRequest, HttpClient, HttpHeaders, HttpEvent, HttpEventType, HttpResponse } from '@angular/common/http'; import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'; import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'; @Component({ selector: 'app-consultation-list', templateUrl: './consultation-list.component.html', styleUrls: ['./consultation-list.component.scss'] }) export class ConsultationListComponent implements OnInit { constructor(private modal: NzModalService,public sanitizer: DomSanitizer,private _myProfileCrudService: MyProfileCrudService,private _http: HttpClient, private _message: NzMessageService) { } public fileList: File[]; public checkName : string = ''; public schedule = '0'; public isUploadVisible: boolean = false; public isUploadDisable: boolean = false; public isOkDisabled : boolean = true; public aiCheckId : number; public ingoreIds : number[] = []; private canceler ; //文件上传过滤器 filters: UploadFilter[] = [ { name: 'type', fn: (fileList: NzUploadFile[]) => { const filterFiles = fileList.filter(w => w.name.search("zip")!=-1); if (filterFiles.length !== fileList.length) { this._message.error(`包含文件格式不正确,只支持 zip 格式`); return filterFiles; } return fileList; } }, { name: 'async', fn: (fileList: NzUploadFile[]) => { if(!this.checkName){ this._message.error(`请输入检查名称`); return null; } return fileList; } } ]; ngOnInit(): void { } //添加执行记录 handleClickOk(){ if(this.schedule != '100.00' && this.schedule != '0'){ this._message.warning("文件上传中...请耐心等候!") return; } if(this.aiCheckId){ let payload = { id: this.aiCheckId, process: "-1", } this._myProfileCrudService.updateAiCheck(payload).subscribe(data=>{ console.log(data) this._message.success("记录添加成功,请执行...") this.getAiExecuteRecords(true) }) } this.isUploadVisible = false; } //取消请求,先加入取消数组中,待第二次执行时取消请求 handleCancel(){ this.confirmModal = this.modal.confirm({ nzTitle: '是否取消?', nzContent: '点击确认后将放弃本次操作', nzOnOk: () =>{ this.isUploadVisible = false; if(this.aiCheckId){ this.ingoreIds.push(this.aiCheckId); } } }); } //显示弹出窗口 handleClick(){ this.schedule = '0'; this.checkName = ''; this.isOkDisabled = false; this.isUploadVisible = true; this.isUploadDisable = false; } beforeUpload = (file: NzUploadFile): boolean => { if(!this.checkName){ this._message.warning("请输入检查名称!") return; } const queryParams = { checkName: this.checkName } //获取文件上传地址 this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => { //上传路径 const uploadUrl = data.data.body.urls.uploadUrl; this.aiCheckId = data.data.body.aiCheckId let File : any = file; //检查文件是否为zip文件,否则不提供上传服务 if((File.name+"").search(".zip")==-1){ this._message.warning("请上传zip文件!") return; } //请求头 const headers = new HttpHeaders() .set('Content-Type','application/zip') //请求对象 const request = new HttpRequest('PUT', uploadUrl, File as File, { headers, reportProgress: true, }); //缓存promise对象 let a = this._http .request(request).subscribe(event => { if(event.type == HttpEventType.UploadProgress){ //如果在取消名单中,执行取消 if(this.ingoreIds && this.ingoreIds.length && this.ingoreIds.indexOf(this.aiCheckId)!=-1){ //取消请求 this.canceler.unsubscribe(); } this.schedule = ((event.loaded/event.total)*100).toFixed(2); console.log(this.schedule) if(!this.isOkDisabled){ this.isOkDisabled = true; } if(!this.isUploadDisable){ this.isUploadDisable = true; } }else if(event instanceof HttpResponse){ console.log('File is completely uploaded!') this.isOkDisabled = false; } }) this.canceler = a; }) return false; }; }
然后文件上传服务就可以随时终止了,你不试一下?