文件拖拽上传
一、JavaScrip
1. 搭建后台环境
1.1 下载依赖
npm init -y
npm install express
npm install formidable
1.2 复制代码
// app.js
// 引入express框架
const express = require("express");
// 路径处理模块
const path = require("path");
const formidable = require("formidable");
// 创建web服务器
const app = express();
app.use((req, res, next) => {
// 1. 允许那些客户端访问我
// * 代表允许所有的客户端访问我
// res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header("Access-Control-Allow-Origin", "*");
// 2. 允许客户端使用哪些请求方法访问我
res.header("Access-Control-Allow-Methods", "get,post");
next();
});
// 实现文件上传的路由
app.post("/upload", (req, res) => {
// console.log(req);
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// // 设置客户端上传文件的存储路径
form.uploadDir = path.join(__dirname, "public", "uploads");
// // 保留上传文件的后缀名字
form.keepExtensions = true;
// // 解析客户端传递过来的FormData对象
form.parse(req, (err, fields, files) => {
// 将客户端传递过来的文件地址响应到客户端
console.log(files);
res.send({
path: files.filename.path,
});
// res.send("ok");
});
});
// 静态资源访问服务功能
app.use(express.static(path.join(__dirname, "public")));
// 监听端口
app.listen(3000);
// 控制台提示输出
console.log("服务器启动成功访问: localhost:3000");
2. 基本骨架
-
在拖动目标上触发事件 (源元素) :
- ondragstart - 用户开始拖动元素时触发
- ondrag - 元素正在拖动时触发
- ondragend - 用户完成元素拖动后触发
-
释放目标时触发的事件:
- ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
- ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
- ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
- ondrop - 在一个拖动过程中,释放鼠标键时触发此事件
注意: 在拖动元素时,每隔 350 毫秒会触发 ondragover 事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style type="text/css">
.container {
padding-top: 60px;
}
.dragger {
width: 200px;
height: 200px;
background-color: pink;
text-align: center;
line-height: 100px;
}
</style>
</head>
<body>
<div class="container">
<div class="dragger">拖拽上传</div>
<p class="pathContent"></p>
</div>
</body>
</html>
3. 阻止浏览器默认打开文件
document.addEventListener("drop", function (e) {
// 拖拽释放
e.preventDefault();
});
document.addEventListener("dragover", function (e) {
//拖来拖去
e.preventDefault();
});
4. 获取文件
// 获取拖拽容器
var dragger = document.querySelector(".dragger");
// 上传文件后路径显示容器
var pathContent = document.querySelector(".pathContent");
drop 事件下的 e.dataTransfer.files 就是存放拖拽的文件的类数组
// 监听拖拽释放事件
dragger.addEventListener("drop", function (e) {
e.preventDefault();
// e.dataTransfer.files 是类数组,将类数组转换成真正的数组
var files = Array.from(e.dataTransfer.files);
}
5. 上传文件
上传文件就是正常发 ajax 请求前后端交互 Ajax,Fetch
// 监听拖拽施放事件
dragger.addEventListener("drop", function (e) {
e.preventDefault();
// e.dataTransfer.files 是类数组,将类数组转换成真正的数组
var files = Array.from(e.dataTransfer.files);
// 创建空的formData表单对象
var formData = new FormData();
// 将用户选择的文件追加到formData表单对象中
formData.append("filename", files[0]);
// 创建 ajax 对象
const xhr = new XMLHttpRequest();
// 设置请求方式和路径
xhr.open("post", "http://localhost:3000/upload");
// 发送请求
xhr.send(formData);
// 监听服务器端响应给客户端的数据
xhr.onload = function () {
if (xhr.status === 200) {
var result = JSON.parse(xhr.responseText);
console.log(result.path);
pathContent.innerHTML = "文件路径" + result.path;
}
};
});
二、React
React 上传文件步骤原生 js 一样, 不过更简单了
import React, { memo, useState } from "react";
export default memo(function App() {
const [path, setPath] = useState("");
const handleDrop = (e) => {
e.preventDefault();
// 获取到文件
const files = Array.from(e.dataTransfer.files);
// 上传文件步骤就和之前一样了
};
return (
<div>
<div
className="dragger"
// 禁止浏览器默认行为
onDrop={handleDrop}
onDragOver={(e) => {
e.preventDefault();
}}
style={{
width: "200px",
height: "200px",
backgroundColor: "pink",
textAlign: "center",
lineHeight: "200px",
}}
>
拖拽上传
</div>
<p>{path}</p>
</div>
);
});
不过这样组件太简陋了,我们可以添加组件添加一些生命周期,上传之前,上传中,上传成功,上传失败等,和一些参数,如请求头,文件名了,是否可以多选了等等。