一、背景
今天说来有点郁闷,大周一的早上的上班就听测试说,st环境的zip文件上传有问题,上传到服务端的zip文件大小和zip源文件的大小有200多bit的差距,导致服务器无法解压zip文件,然后无法读取和解析dicom文件。。。最后导致服务器无法正常运行(经过了dev和release环境的测试,咋就没测试出来呢?吐槽一下!)。然后又说那个啥UI不行,需要添加那个文件上传进度条。你UI设计的时候咋就不设计好呢?不吐槽了,我是吃这碗饭的,好好干吧!
二、bug定位
「这个多出的bit是哪里来的呢?怎么定位呢?思路如下:」
- 读取文件时,流的大小有变化
- 表单上传时,文件流大小有变化
- 后端接收流时是正常的,但是经过处理后,流的大小有变化
顺着这个思路:
- 我第一步就是在后端断点,远程逐步debugger文件流大小是否有变化。具体操作步骤可参考超简单!docker容器远程debugger(springboot),然后发现并没有什么问题。
- 第二步就是自己本地启动一个服务,后端链接st环境的地址。打开F12,一路追踪下去,从读取到表单都是和源文件大小一致的。
- 但是当我发起上传请求的时候,出现了下面的一段描述:
- 我上传的zip文件里面是没有这个东西,于是大胆的猜测,这里会不会是导致文件大小不一样的原因,于是我修改了表单上传请求的方式为body上传,结果发现果然是表单上传的问题。
- 表单上传代码,接收文件比上传文件大200bit
// beforeUpload = (file: NzUploadFile): boolean => { const queryParams = { checkName: this.checkName } //获取上传路径 this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => { const uploadUrl = data.data.body.urls.uploadUrl; let File : any = file; //表单上传文件 const formData = new FormData(); formData.append('file', File as File); const headers = new HttpHeaders() .set('Content-Type','application/zip') const request = new HttpRequest('PUT', uploadUrl, formData, { headers }); this._http .request(request).subscribe(data => { this.getAiExecuteRecords(true); }) }) return false; };
- body上传代码
beforeUpload = (file: NzUploadFile): boolean => { const queryParams = { checkName: this.checkName } this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => { const uploadUrl = data.data.body.urls.uploadUrl; let File : any = file; //设置请求头 const headers = new HttpHeaders() .set('Content-Type','application/zip') //创建request对象 const request = new HttpRequest('PUT', uploadUrl, File as File, { headers }); this._http .request(request).subscribe(event => { if(event.type == HttpEventType.UploadProgress){ this.schedule = ((event.loaded/event.total)*100).toFixed(2); console.log(this.schedule) }else if(event instanceof HttpResponse){ console.log('File is completely uploaded!') } this.getAiExecuteRecords(true) }) }) return false; };
- 修改后结果如下:
三、文件上传显示进度条
1.html代码
<nz-modal nzWidth="400px" [(nzVisible)]="isUploadVisible" nzTitle="" (nzOnCancel)="handleCancle()" (nzOnOk)="handleCancle()"> <div> <input nz-input style=" width: 300px; height: 40px; background: #F1F1F1; border-radius: 6px;" 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>选择文件</button> </nz-upload> <div style="width: 310px; height:40px;margin-top:26px"> <nz-progress [(nzPercent)]="schedule"></nz-progress> </div> </nz-modal>
2. js代码(angular)
//初始进度为0 public schedule = '0'; //默认弹窗不显示 public isUploadVisible: boolean = false; //处理上传弹窗点击事件 handleClick(){ this.schedule = '0'; this.isUploadVisible = true; } //处理关闭事件 handleCancle(){ if(this.schedule != '100' && this.schedule != '0'){ this._message.warning("文件上传中...请耐心等候!") return; } this.isUploadVisible = false; } //处理上传逻辑 beforeUpload = (file: NzUploadFile): boolean => { const queryParams = { checkName: this.checkName } this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => { const uploadUrl = data.data.body.urls.uploadUrl; let File : any = file; //请求头 const headers = new HttpHeaders() .set('Content-Type','application/zip') //开启reportProgress,必须,不然无法获取进度 const request = new HttpRequest('PUT', uploadUrl, File as File, { headers, reportProgress: true, }); this._http .request(request).subscribe(event => { // 如果Http事件类型为上传,则计算进度 = (加载数/总数)*100 if(event.type == HttpEventType.UploadProgress){ this.schedule = ((event.loaded/event.total)*100).toFixed(2); console.log(this.schedule) }else if(event instanceof HttpResponse){ console.log('File is completely uploaded!') } this.getAiExecuteRecords(true) }) }) return false; };
至此,上传文件大小不符的bug解决,文件上传显示进度的需求解决。