Angular+PrimeNG文件上传选中文件无法清除及优化需求
问题根源分析
- 文件选择残留:点击取消按钮时仅调用了
fileUpload.clear(),但未清空存储文件的base64DataArray和uploadedFiles数组;且onSelect事件每次触发都会追加文件到数组,导致旧文件残留重复上传,最终触发413请求体过大错误。 - 大文件适配问题:将文件转成base64会让体积膨胀约30%,既占用大量客户端内存,又极易触发后端的请求体限制,这种方式仅适合小文件场景。
解决方案
1. 修复文件清除与重复选择问题
- 绑定
fileUpload的onCancel事件,触发时彻底清空所有文件数组和组件状态 onSelect触发时先清空旧数组,避免追加重复文件- 上传成功/失败后统一重置相关数组和组件状态
2. 优化大文件上传逻辑
- 放弃base64转码,改用
FormData直接上传文件,避免体积膨胀和内存占用问题 - 调整服务调用逻辑,适配FormData格式传递
修改后的代码
component.ts
import { Component, ViewChild } from '@angular/core'; import { FileUpload } from 'primeng/fileupload'; uploadedFiles: any[] = []; base64DataArray: any[] = []; @ViewChild('fileUpload') fileUpload: FileUpload; getTokenUpload(user: string, ci: string) { this.service.getToken(environment.SCOPES["carga"]).subscribe( (data: any) => { const token = data.access_token; this.onUploadWithFormData(user, ci, token); this.resetFileUpload(); }, (error) => { console.error('获取token失败: ', error); this.resetFileUpload(); } ); } onUploadWithFormData(user: string, ci: string, token: string) { this.blockUI.start("上传中..."); const formData = new FormData(); formData.append('user', user); formData.append('ci', ci); this.fileUpload.files.forEach(file => { formData.append('files[]', file, file.name); }); this.service.uploadFilesWithFormData(formData, token).subscribe( () => { this.showUploadFiles = false; this.blockUI.stop(); this.showMessage('success', '成功', '文件上传完成'); this.getToken(); this.resetFileUpload(); }, (error) => { console.error('上传失败: ', error); this.showMessage('error', '上传失败', '文件上传出现错误'); this.blockUI.stop(); this.resetFileUpload(); } ); } onFileSelected(event: any): void { this.uploadedFiles = []; this.base64DataArray = []; const files = event.files; if (files && files.length > 0) { this.uploadedFiles = files.map(file => ({name: file.name, size: file.size})); // 若仍需处理小文件base64,可保留下方代码 // this.convertToBase64Array(files); } } resetFileUpload(): void { if (this.fileUpload) { this.fileUpload.clear(); } this.uploadedFiles = []; this.base64DataArray = []; } convertToBase64Array(files: File[]): void { for (const file of files) { const reader = new FileReader(); reader.onload = (e: any) => { let base64Data = e.target.result; base64Data = this.getBase64WithoutPrefix(base64Data); this.base64DataArray.push({ filename: file.name, file: base64Data }); }; reader.readAsDataURL(file); } } getBase64WithoutPrefix(base64Data: string): string { return base64Data.replace(/^data:[^;]+;base64,/, ''); }
HTML代码
<p-dialog [(visible)]="showUploadFiles" [style]="{width: '1050px'}" header="选择文件" [modal]="true" styleClass="p-fluid" [resizable]="true"> <p-fileUpload #fileUpload name="files[]" (onBeforeUpload)="getTokenUpload(user, ci)" (onSelect)="onFileSelected($event)" (onCancel)="resetFileUpload()" [multiple]="true" accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,.rar,.webp" maxFileSize="187286400" chooseLabel="选择文件" uploadLabel="上传" cancelLabel="取消"> <ng-template pTemplate="content"> <ul *ngIf="uploadedFiles.length"> <li *ngFor="let file of uploadedFiles">{{ file.name }} - {{ file.size }} bytes</li> </ul> </ng-template> </p-fileUpload> </p-dialog>
服务端调用调整(service.ts示例)
uploadFilesWithFormData(formData: FormData, token: string): Observable<any> { const headers = new HttpHeaders({ 'Authorization': `Bearer ${token}` }); return this.http.post(`${environment.apiUrl}/upload`, formData, { headers }); }
关键说明
- 状态统一重置:通过
resetFileUpload()方法集中处理组件和数组的清空逻辑,确保取消、成功、失败场景下都能彻底清除旧文件 - 大文件适配:FormData是浏览器原生支持的文件上传方式,不会增加文件体积,后端只需按
multipart/form-data格式接收即可 - 类型安全优化:将
fileUpload的类型从any改为FileUpload,避免潜在的类型错误
内容的提问来源于stack exchange,提问作者Bet
相关产品推荐
相关产品推荐

