我有Angular应用程序,用户可以在其中将文件上传到服务器。 通过以下方式接收文件(不删除相关代码):
@Component({
selector: "app-select-file-button",
template: `
<input type="file" (change)="handleInputChange($event)">
`
})
export class SelectFileButtonComponent {
@Output() file: EventEmitter<File> = new EventEmitter<File>();
handleInputChange(e: any) {
this.file.emit(e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0]);
}
}
所以这是一个普通的文件选择。 之后,我可以向用户显示他选择了哪个文件,文件大小等。
但是,我有下一个用例。用户可能错误地选择了错误的文件,甚至看不到文件名和大小。因此,我需要显示文件的用户内容。
我真正要避免的是实现方案,即用户将错误的文件上传到服务器,然后看到指向已上传文件的链接,进行下载,检查,理解错误,然后再次上传正确的文件。
文件可以不同-pdf,doc,档案,大型mp3文件。 我已经实现了在新的iframe中显示文件:
const reader = new FileReader();
reader.onload = (e: any) => {
this.base64Url = e.target.result;
const win = window.open();
win.document.write('<iframe src="' + this.base64Url + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen download></iframe>');
};
reader.readAsDataURL(file);
此方法有两个问题:
首先,该方法不适用于Chrome上的mp3文件,因为它尝试播放音频并且什么也没发生(可以显示其他文件或立即下载其他文件,这很好)
其次,据我了解,使用fileReader将该文件存储在RAM中。 mp3文件可能很大(大约数百MB),通常是从手机上载的,而内存可能有限。
可以使用更好的方法吗?如果没有,如何强制浏览器开始下载mp3文件而不是打开它们?可以在一个框架中为文件设置正确的名称吗?
答案 0 :(得分:0)
我发现解决方案比预期的简单得多。 最主要的是,我已经有一个文件blob,因此不需要转换为base64url。 另外,浏览器默认情况下会阻止从代码打开的URL,因此需要使用角度清理器:
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
在组件中注入消毒剂:
constructor(private _sanitizer: DomSanitizer) {}
选择文件html:
<input type="file" (change)="handleInputChange($event)">
获取文件Blob代码:
handleInputChange(e: any) {
this.file = e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0];
}
已创建并清除网址:
const w: any = window;
this.url = this._sanitizer.bypassSecurityTrustResourceUrl((w.webkitURL || w.URL).createObjectURL(this.file));
在URL中使用“下载”参数(因此浏览器不会尝试打开文件,而只是使用正确的名称下载文件):
<a [href]="url" [download]="file.name">{{file.name}}</a>