Angular用复制粘贴方式上传文件



在我的应用程序中,我有一个Upload按钮,使用户能够搜索文件并上传它们。我还定义了一个textarea,我希望用户能够粘贴他复制的文件并以这种方式上传(就像你在电子邮件或whatsapp等中所做的那样)。现在,当我试图粘贴我复制的文件时,什么也没有发生,文件也没有粘贴。我的代码如下。我应该怎样用粘贴方式上传文件?

HTML:

<div>
<button mat-stroked-button class="primary-fg" (click)="onFileUploadClick($event)">
<mat-icon>attach_file</mat-icon>
Upload
</button>
<mat-form-field appearance="fill">
<mat-label>Paste</mat-label>
<textarea matInput
cdkTextareaAutosize
#autosize="cdkTextareaAutosize"
cdkAutosizeMinRows="1"
cdkAutosizeMaxRows="5"
id="pasteArea"></textarea>
</mat-form-field>
<script>
window.addEventListener("paste", e => {
if (e.clipboardData.files.length > 0) {
const fileInput = document.querySelector("#fileInput");
fileInput.files = e.clipboardData.files;
}
});
</script>
</div>
<input hidden type="file" id="fileInput" #fileInput multiple />

TS:

onFileUploadClick(event: any) {
event.preventDefault();
const fileInput = document.getElementById('fileInput') as HTMLInputElement;
fileInput.value = '';
fileInput.onchange = () => {
let tempFiles: IAttachment[] = [];
for (let index = 0; index < fileInput.files.length; index++) {
const file = fileInput.files[index];
const fileSize = file.size / 1024 / 1024; // in MB
if (fileSize <= 5) {
tempFiles.push({ FileInfo: file });
}
else {
this._dialog.open(FuseSimpleDialogComponent, {
width: "400px",
data: {
title: "Uyarı",
message: "Dosya boyutu 5MB'den büyük olduğundan seçilemez. Dosya Adı: " + file.name
}
});
}
}
tempFiles.forEach(f => this.uploadFile(f));
};
fileInput.click();
}
/**
* 
* @param file
*/
private uploadFile(file: IAttachment) {
if (file.FileData) return; //file already uploaded
let fileReader: FileReader = new FileReader();
let $that = this;
let data: any;
fileReader.onerror = function (): void {
//show error message
};
fileReader.onloadend = function (): void {
if (FileReader.prototype.readAsBinaryString) {
data = btoa(fileReader.result as string);
}
else { //support for IE
data = ($that as any).arrayBufferToBase64(fileReader.result);
}
file.Name = file.FileInfo.name;
file.FileData = data;
file.CreateDate = new Date();
file.CreateUser = $that.user;
let allFiles = $that.Attachments ? $that.Attachments.slice(0) : [];
allFiles.unshift(file);
$that.Attachments = allFiles;
$that.AttachmentsChange.emit(allFiles);
};
if (FileReader.prototype.readAsBinaryString) {
fileReader.readAsBinaryString(file.FileInfo);
}
else { //support for IE
fileReader.readAsArrayBuffer(file.FileInfo);
}
}

小心你的方法,简单地粘贴一个文件到textarea将做什么作为文本区域接收…文本。

您需要在组件的某个地方有一个input file,并在window上为paste事件设置一个事件侦听器。

然后采取粘贴事件,并尝试看看它是否包含一个文件,如果是,开始上传过程,如果没有,粘贴文本在textarea

这就是我的做法。

我使用HostListener尝试了同样的事情,它为我工作。为了供您参考,我将附上我的TS, HTML和SCSS文件。

HTML:

<div class="file-drop-area" *ngIf="!multiple">
<button mat-raised-button color="primary">Choose file</button>
<span>{{ file ? file.name : " or drag and drop file here" }}</span>
<input class="file-input" type="file" />
</div>
<div class="file-drop-area" *ngIf="multiple">
<button mat-raised-button color="primary">Choose files</button>
<span *ngIf="!fileList">{{ " or drag and drop files here" }}</span>
<input class="file-input" type="file" multiple />
</div>
<div class="col-md-12 mt-2" *ngIf="multiple">
<span *ngFor="let file of arrFileList; let index = index"
>{{ file.name }}
<app-feather-icons
[icon]="'trash-2'"
[class]="'tbl-fav-delete'"
(click)="removeSelectedFile(index)"
>
</app-feather-icons>
&nbsp;&nbsp;
</span>
</div>

TS:

/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/ban-types */
import { Component, ElementRef, HostListener, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-file-upload',
templateUrl: './file-upload.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: FileUploadComponent,
multi: true,
},
],
styleUrls: ['./file-upload.component.scss'],
})
export class FileUploadComponent implements ControlValueAccessor {
@Input()
multiple = false;
onChange!: Function;
public file: File | null = null;
public fileList: FileList | null = null;
public arrFileList = [];
@HostListener('change', ['$event.target.files']) emitFiles(event: FileList) {
if (event && event.length === 1 && !this.multiple) {
const file = event && event.item(0);
this.onChange(file);
this.file = file;
} else if (event && event.length > 0 && this.multiple) {
console.log(event);
const fileList = event;
this.fileList = fileList;
this.arrFileList = Array.from(fileList);
this.onChange(this.arrFileList);
this.writeValue(null);
}
}
@HostListener('window:paste', ['$event']) onPaste(event: ClipboardEvent) {
if (event && event.clipboardData.files.length > 0) {
if (event.clipboardData.files.length === 1 && !this.multiple) {
const file = event.clipboardData.files[0];
this.onChange(file);
this.file = file;
} else if (this.multiple) {
console.log(event);
const fileList = event.clipboardData.files;
this.fileList = fileList;
this.arrFileList = Array.from(fileList);
this.onChange(this.arrFileList);
this.writeValue(null);
}
}
}
constructor(private host: ElementRef<HTMLInputElement>) {}
removeSelectedFile(index) {
// Delete the item from fileNames list
this.arrFileList.splice(index, 1);
this.onChange(this.arrFileList);
}
writeValue(value: null) {
// clear file input
this.host.nativeElement.value = '';
this.file = null;
this.fileList = null;
}
registerOnChange(fn: Function) {
this.onChange = fn;
}
registerOnTouched(fn: Function) {
// add code here
}
}

SCSS:

.file-drop-area {
border: 1px dashed #7c7db3;
border-radius: 3px;
position: relative;
max-width: 100%;
margin-top: 5px;
padding: 26px 20px 30px;
transition: 0.2s;
}
.file-input {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
cursor: pointer;
opacity: 0;
}
.file-msg {
display: inline-block;
margin-left: 5px;
font-size: 12px;
font-weight: 500;
color: #5b5bff;
}

最新更新