一、前言
老规矩,每篇开篇之前先啰嗦一下吧。昨天刚刚把那个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;
};
}
然后文件上传服务就可以随时终止了,你不试一下?
}else if(event instanceof HttpResponse){
console.log('File is completely uploaded!')
this.isOkDisabled = false;
}
})
this.canceler = a;
})
return false;
};
}
然后文件上传服务就可以随时终止了,你不试一下?