我不久前整理的基本文件放置组件:
file-drop.component.ts
import { Component, ElementRef, ViewChild, EventEmitter, Output } from '@angular/core';
/**
* Basic component to provide file drag & drop (and click) functionality
* for uploading files using HTML file API.
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop
*
* Note if looking at the debug console in FF and find the drop dataTransfer
* value to be null - that's only a debug display issue with FF.
* https://stackoverflow.com/a/60305243/1585218
*/
@Component({
selector: 'app-file-drop',
templateUrl: './file-drop.component.html',
styleUrls: ['./file-drop.component.scss']
})
export class FileDropComponent {
private _isDragging: boolean;
constructor() { }
@ViewChild('fileSelector') public fileSelector: ElementRef;
@Output() public selectedFiles = new EventEmitter<File[]>();
public get isDragging(): boolean { return this._isDragging; }
public onDrop(event: any): void {
// Stop browser opening the file
event.preventDefault();
this._isDragging = false;
const result = [];
if (event.dataTransfer.items) {
// Use DataTransferItemList interface to access the file(s)
for (const item of event.dataTransfer.items) {
if (item.kind !== 'file') {
return;
}
result.push(item.getAsFile());
}
} else {
// Use DataTransfer interface to access the file(s)
for (const file of event.dataTransfer.files) {
result.push(file);
}
}
this.emitFiles(result);
}
public onFilesSelected(files: any[]): void {
if (files == undefined || files.length === 0) {
return;
}
const result = [];
for (const file of files) {
result.push(file);
}
this.fileSelector.nativeElement.value = ''; // required to trigger (change) if user immediately uploads same named file
this.emitFiles(result);
}
public onDragOver(event: any): void {
// Stop browser opening the file
event.preventDefault();
this._isDragging = true;
}
public stopDrag(event: any): void {
this._isDragging = false;
event.preventDefault();
event.stopPropagation();
}
private emitFiles(files: File[]): void {
this.selectedFiles.emit(files);
}
}
文件-drop.component.html
<div class="component-container"
[class.hovering]="isDragging"
(click)="fileSelector.click()"
(drop)="onDrop($event)"
(dragover)="onDragOver($event)"
(dragleave)="stopDrag($event)"
(dragend)="stopDrag($event)">
<div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
<div class="text">Drag & drop or click</div>
<input #fileSelector type="file" multiple (change)="onFilesSelected($event.target.files)" hidden>
</div>
文件-drop.component.scss
.component-container {
text-align: center;
padding: 1em;
width: 100%;
height: 100%;
}
.component-container:hover,
.hovering {
cursor: pointer;
background-image: -webkit-linear-gradient(135deg,#F6F6F6 25%,transparent 25%,transparent 50%,#F6F6F6 50%,#F6F6F6 75%,transparent 75%,transparent);
animation: stripes 2s linear infinite;
background-size: 30px 30px;
background-color: #fff;
}
.icon {
font-size: 1.5em;
}
.text {
font-size: 0.8em;
}
.icon, .text {
margin: auto;
}
@-webkit-keyframes stripes {
from {
background-position: 0 0; }
to {
background-position: 60px 30px; } }
@keyframes stripes {
from {
background-position: 0 0; }
to {
background-position: 60px 30px; } }
基本用法:
<app-file-drop (selectedFiles)="onFilesSelected($event)"></app-file-drop>
...
public onFilesSelected(files: File[]): void {
for (const file of files) {
console.log('File:', file);
}
}