Angular中使用drag and drop实现文件拖拽上传,及flask后端接收

效果:拖拽文件到组件上面时 边框变大变红 松手后发送到服务器(或者点击蓝字手动选择文件)并且把文件名显示在框内,美化还没做




html

html 复制代码
<div class="drapBox">
    <div id="drop" (dragenter)="dragenter($event)" (dragover)="dragover($event)" (dragleave)="dragleave($event)"
        on-drop="drop($event)" [ngClass]="{'dragover':isdragover,'notdragover':!isdragover}">
        <div class="desc">Drag files here, or</div>
        <label for="file" class="input_desc">
            <input class="drag-message-input" type="file" id="file" name="file" on-change="inputFile($event)" />
            <span class="drag-message-manual">click to select</span>
        </label>
    </div>
    <div id="selectedFilesBox" class="absflex" *ngIf="selectedFilesName.length>0">
        <div class="allFileDesc">{{selectedFilesCount}} files selected:</div> 
        <div class="fileDesc" *ngFor="let item of selectedFilesName">{{item}}</div>
    </div>
</div>

Ts

javascript 复制代码
import { Component } from '@angular/core';
import { Observable, catchError, of, switchMap } from 'rxjs';
import { HttpClient } from '@angular/common/http';
@Component({
  selector: 'app-filedrag',
  templateUrl: './filedrag.component.html',
  styleUrls: ['./filedrag.component.css']
})
export class FiledragComponent {
  isdragover:boolean=false;
  selectedFilesName:string[]=[];
  selectedFilesCount:number = 0;
  constructor(private http: HttpClient){}
  dragover(e:Event){
    e.stopPropagation();
    e.preventDefault();
    this.isdragover=true;
    console.log("dragover");
  }
  dragleave(e:Event){
    e.stopPropagation();
    e.preventDefault();
    this.isdragover=false;
    console.log("dragleave");
  }
  dragenter(e:Event){
    e.stopPropagation();
    e.preventDefault();
    console.log("dragenter");
  }
  drop(e:any){
   e.stopPropagation();
   e.preventDefault();
   this.isdragover=false;
   let dataTransfer=e.dataTransfer;
   let files=dataTransfer.files;
   console.log("files:");
   console.log(files);
   this.showSelectedFiles(files);
   this.handleFiles(files).subscribe();
 }
 inputFile(e:any){
  console.log(e.target.files);
  this.showSelectedFiles(e.target.files);
  this.handleFiles(e.target.files).subscribe();
}
showSelectedFiles(files: FileList): void{
  this.selectedFilesName = [];
  this.selectedFilesCount = files.length;
  for(let i=0;i<files.length;i++){
    this.selectedFilesName.push(files[i].name);
  }

}
handleFiles(filesToUp: FileList): Observable<{message:string}> {
  const url: string = "http://127.0.0.1:5000/up_file";
  const formData: FormData = new FormData();
  for(let i=0;i<filesToUp.length;i++){
    formData.append('files', filesToUp[i]);
  }
  return this.http
    .post<any>(url, formData).pipe(
      switchMap((res: {message:string}) => { console.log(res); return of(res); }),
      catchError(er=>{console.log(er);return of({message:"error"})})
    );
}

}

Css

css 复制代码
.drapBox{
    position: relative;
    width: 300px;
    height: 300px;
}
#drop {
    position: absolute;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;

}
.dragover{
    border: 2px dashed red;
    zoom:108%;
}
.notdragover{
    border: 2px dashed grey;
}


#file {
    display: none;
}
.desc{
    font-size: 1rem;
}
.input_desc {
    padding-left: 5px;
    font-size: 1rem;
    color: #4b87ff;
    cursor: pointer;
}
.absflex{
    position: absolute;
    width: 100%;
    height: 100%;
}
.allFileDesc{
    padding: 5px;
}
.fileDesc{
    display: inline-block;
    padding: 5px;
    border: 1px solid #4b87ff;
    font-style: italic;
    width: auto;
    height: 20px;
}

后端python flask代码一起贴上

python 复制代码
# -*- coding: utf-8 -*-
from flask import Flask,request
from flask import send_from_directory,render_template
from flask_cors import CORS

# r'/*' 是通配符,让本服务器所有的URL都允许跨域请求

app = Flask(__name__)
CORS(app, resources=r'/*')
@app.route("/up_file", methods=["POST", "GET"])
def file_receive():
    # try:
    files = request.files.getlist("files")
    print(files)
    if files is None:  # 表示没有发送文件
        return {
            'message': "failed"
        }
    else:
        return {
                   'message': "success"
        }
if __name__ == '__main__':
    app.run(debug=True)
相关推荐
m0_719084111 小时前
React笔记张天禹
前端·笔记·react.js
Ziky学习记录1 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
wuhen_n1 小时前
JavaScript链表与双向链表实现:理解数组与链表的差异
前端·javascript
wuhen_n1 小时前
JavaScript数据结构深度解析:栈、队列与树的实现与应用
前端·javascript
狗哥哥2 小时前
微前端路由设计方案 & 子应用管理保活
前端·架构
前端大卫2 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘2 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare2 小时前
浅浅看一下设计模式
前端
Lee川3 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix3 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts