基于拖拽实现文件上传
-
准备一个页面,
02_upload.html
. 提供一个div
, 监听drop
事件. 在该事件的处理函数中接收用户拖拽进来的文件信息. -
一旦获取到文件信息, 需要遵守
http
协议规范下上传文件的标准, 发送上传文件请求, 将文件数据发给服务端. -
服务端接收并存储该文件, 保存在服务器文件系统内部(
/home/a.jpg
) -
保存完毕后, 即上传成功, 之后浏览器可以通过链接地址访问该资源.
如何获取拖拽文件的信息?
当用户把文件拖拽到div
中并触发drop
事件后, 浏览器将会把拖拽的文件的基本信息, 存入event.dataTransfer
. 那么意味着我们可以在drop
事件处理函数中通过event.dataTransfer
获取拖拽的文件基本信息:
let files = event.dataTransfer.files
文件上传流程与协议规范
文件上传流程:
客户端选择需要上传的文件, 点击上传, 开始建立连接, 准备上传.
服务端接收连接请求,完成连接的建立, 接收上传的文件(遵守协议).
服务端将接收到的文件数据,存入服务器文件系统(
D:/xxx.mp3
).保存完毕后即上传成功, 之后浏览器可以根据某个链接地址访问资源.
协议规范:
要求客户端提交文件的请求方式必须是
POST
.发请求时必须携带请求消息头:
Content-Type: multipart/form-data
.客户端将本地文件在请求
body
部分中以数据流的方式传输给服务端.服务端接收客户端传来的数据流, 边接收, 边保存到服务端磁盘中.
客户端发送上传文件请求
客户端发送上传文件请求时的方式有两种:
-
基于表单发送上传文件请求.
-
基于
ajax
发送上传文件请求.
基于表单发送上传文件请求实现文件上传时, 需要注意一下协议规则:
必须整理表单.
<form> </form>
表单提交方式必须是
post
.设置表单的属性:
<form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="uploadFile"> <input type="submit" value="提交"> </form>
基于ajax
发送上传文件请求优点就是异步发送请求, 上传文件的基本写法如下: (在此引入axios
, 使用axios
发送ajax
请求):
// 封装表单参数, html5提供了 FormData 用于封装表单参数
let formdata = new FormData();
formdata.append('name', 'zhangsan') // name=zhangsan
formdata.append('age', 17) // name=zhangsan&age=17
formdata.append('uploadFile', filelist[0])
// name=zhangsan&age=17&uploadFile=FileObj
axios.post('http://localhost:3000/upload', formdata)
为什么页面刷新了?
使用ajax
发送上传文件请求, 若该上传文件请求为跨域请求, 则浏览器接收到响应之后将会自动刷新页面. 若不希望页面自动刷新, 可以控制避免该请求为跨域请求.
如何访问已经上传的资源?
最基础的方法:
服务端将
upload
目录设置为静态托管目录.客户端可以直接发请求, 访问
upload
目录下的资源:http://localhost:3000/1b8a8371-2afd-4355-99e3-e8a23711514f.jpg
进阶版:
客户端上传的文件将会交给一个专业的静态资源服务器. 该静态资源服务器将会返回一个访问链接.
客户端下次直接访问该链接即可获取静态资源服务器中的资源.
以上传头像为例:
-
在服务端
mysql
数据库中存储用户的基本信息.ID name age avatar
zs 13 1234.jpg2
ls 15 2345.jpg
-
客户端登录成功后, 选择新头像, 执行上传业务.
-
服务端通过
multer
中间件将上传上来的文件重命名, 保存到头像目录中. -
保存成功后, 需要将新的头像文件名更新到数据库:
ID name age avatar
1 zs 13 abaab-865a-s95d-fa9s.jpg
2 ls 15 2345.jpg
-
当
zs
再次登录时, 就可以直接获取到数据库中存储的最新的头像路径, 在页面中显示即可.
服务端到底怎么保存的上传上来的文件?
基于multer
中间件实现文件的接收与保存.