惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
L
LINUX DO - 最新话题
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
S
Schneier on Security
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
P
Privacy & Cybersecurity Law Blog
S
Security Archives - TechRepublic
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Attack and Defense Labs
Attack and Defense Labs
Hacker News: Ask HN
Hacker News: Ask HN
S
Security @ Cisco Blogs
S
Secure Thoughts
C
CERT Recently Published Vulnerability Notes
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Cybersecurity and Infrastructure Security Agency CISA
The Last Watchdog
The Last Watchdog
T
Tenable Blog
SecWiki News
SecWiki News
T
The Exploit Database - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
N
News and Events Feed by Topic
E
Exploit-DB.com RSS Feed
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
L
LINUX DO - 热门话题
The Hacker News
The Hacker News
P
Privacy International News Feed
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 叶小钗
Cloudbric
Cloudbric
小众软件
小众软件
月光博客
月光博客
S
Securelist
V
V2EX - 技术
I
Intezer
M
MIT News - Artificial intelligence
aimingoo的专栏
aimingoo的专栏
S
Security Affairs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
F
Full Disclosure
A
About on SuperTechFans

博客园 - Xproer-松鼠

PHP实现视频文件上传完整实例 ueditor 富文本编辑器粘贴图片时让图片居中 TinyMCE富文本编辑器粘贴图片自动上传问题解决 UEditor富文本编辑器图片粘贴和上传问题 vue项目中使用tinymce富文本编辑器实现图片上传/粘贴格式 富文本编辑器复制word文档中的图片 富文本编辑器:自己实现图片上传功能和图片粘贴上传(kindeditor) 前端上传文件或者上传文件夹 HTML5应用之文件拖拽上传 使用HTML5实现多文件上传 HTML5 文件上传的2种方式 html5实现文件批量上传组件 HTML5文件上传操作 html5中怎么实现多文件上传功能 HTML5 进阶系列:文件上传下载 html实现上传 大文件分片上传 【前后台完整版】大文件分片上传 大文件、视频分片上传,断点续传
前端实现文件上传(点击+拖拽)
Xproer-松鼠 · 2023-12-26 · via 博客园 - Xproer-松鼠

一、简介
之前在Vue项目中使用过element的上传组件,实现了点击上传+拖拽上传的两种上传功能。然后我就在想是否可以通过原生的html+js来实现文件的点击上传和拖拽上传,说干就干。
首先是点击获取上传文件自然没的说,只需要借助input标签即可,但原生的点击上传按钮,实在是过于简陋,所以我的想法是通过一个div,模拟成上传按钮,然后监听其点击事件,通过input.click()去模拟点击真正的上传元素。
然后是拖拽获取上传文件,这个稍有难度,我的想法是通过HTML5新增的drag拖放API+dataTransfer来实现文件的拖拽获取,但是由于是html5新增的,所以可能在某些低版本IE浏览器不兼容,所以如果要在实际企业级项目中使用,需要注意一下兼容性问题(IE该死!)。

最后当我们获取到上传文件之后,我们就可以借助formDate对象以及ajax工具(原生、jquery、axios等)进行文件上传了,而且我们还可以通过xhr.upload.onprogress获取文件上传的进度在页面中进行展示。

二、获取文件
1、页面效果


2、点击和拖拽上传获取的文件结果

3、具体代码
<style>
.box {
width: 300px;
height: 300px;
margin: 50px auto;
padding-top: 30px;
background-color: #f5f5f5;
border-radius: 10px;
}
.btn {
width: 200px;
height: 30px;
line-height: 30px;
margin: 10px auto;
text-align: center;
color: #5098F8;
border-radius: 4px;
border: 1px dashed #5098F8;
cursor: pointer;
}
</style>

<body>
<!-- 这个id属性放在哪个盒子里面 哪个盒子的范围就是拖拽上传的范围 -->
<div class="box" id="drop">
<!-- 用来展示的上传按钮 -->
<div class="btn" id="btn">点击上传按钮</div>
<!-- 实际实现上传的input 并限制文件类型(不保险,因为用户可以放手放开限制,选择所有类型文件,所以需要在上传之前进行第二次验证) -->
<input type="file" id="file-btn" onchange="selectFile(event)" accept=".doc,.docx" style="display: none;">
</div>

<script>
var file = null // 要进行上传的文件
// 给上传按钮绑定点击事件
document.querySelector('#btn').onclick = function() {
// 模拟点击上传的input 弹出文件选择框
document.querySelector('#file-btn').click()
}
// 获取点击上传 选择的文件
function selectFile(e) {
// 通过 e.target.files 获取到选择的文件 此处默认选择一个文件
console.log('获取点击上传的文件---',e.dataTransfer.files[0]);
// 第二次验证选择的文件类型是否正确
if(e.target.files[0].type == 'application/msword' || e.target.files[0].type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
file = e.target.files[0]
} else {
alert('请选择正确的文件类型')
}
}

// 拖拽上传获取对应文件
let dropBox=document.querySelector('#drop');
// 当文件在目标元素内移动时
dropBox.addEventListener('dragover',function(e){
// 阻止事件冒泡
e.stopPropagation();
// 阻止默认事件(与drop事件结合,阻止拖拽文件在浏览器打开的默认行为)
e.preventDefault();
})
// 当拖拽文件在目标元素内松开时
dropBox.addEventListener('drop',function(e){
// 阻止事件冒泡
e.stopPropagation();
// 阻止默认事件(与dragover事件结合,阻止拖拽文件在浏览器打开的默认行为)
e.preventDefault();
// 获取拖拽上传的文件(files是个数组 此处默认限制只能上传一个)
console.log('获取拖拽上传的文件---',e.dataTransfer.files[0]);
// 第二次验证选择的文件类型是否正确
if(e.dataTransfer.files[0].type == 'application/msword' || e.dataTransfer.files[0].type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
file = e.dataTransfer.files[0]
} else {
alert('请选择正确的文件类型')
}
})
</script>
</body>


注:用户手动放开限制操作(此处以mac电脑为例,windows电脑也相差不多),只需下面三步:


三、进行上传
我们需要借助formDate对象以及ajax工具(原生、jquery、axios等)进行文件上传,而且我们还可以通过xhr.upload.onprogress获取文件上传的进度在页面中进行展示,不过我们通过xhr.upload.onprogress获取的仅仅是文件上传到服务器的进度,并不包括服务器进行处理以及基于前端响应的这部分时间,所以会当前端文件上传到100%后,会停滞一段时间才能获得服务端的响应。
此处列举两种方式:原生ajax和axios。

1、原生ajax
// 上传函数
function uplaod() {
// 创建 FormData 对象
var formData = new FormData();
// 将获得文件对象追加到 FormData 对象中
formData.append('file',file)
// 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 POST
xhr.open('POST', 'www.baidi.com')
// 发起请求
xhr.send(fd)
// 监听 xhr.upload 的 onprogress 事件 获取上传进度
xhr.upload.onprogress = function(e) {
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// Math.round() 进行四舍五入取整 因为上传时 网络等不确定因素可能会出现缺失小部分字节的情况
// e.loaded 已传输的字节
// e.total 需传输的总字节
var progress = Math.round((e.loaded / e.total) * 100) + '%'
}
}
// 是否上传成功
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if (data.status === 200) {
console.log('上传文件成功');
}
}
}


2、axios(vue)
// 上传函数(vue中)
async uplaod() {
// 创建 FormData 对象
var formData = new FormData();
// 将获得文件对象追加到 FormData 对象中
formData.append('file',file)
try {
// 暂存this对象
const that = this
// 调用接口开始上传
await this.$axios.post(api.addfiles, formData, {
// 实时获取上传进度
onUploadProgress (progressEvent) {
// Math.round() 进行四舍五入取整 因为上传时 网络等不确定因素可能会出现缺失小部分字节的情况
// loaded 已传输的字节
// total 需传输的总字节
that.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100) + '%'
}
console.log('上传成功')
} catch(error) {
console.log('上传失败',error)
}

参考文章:http://blog.ncmem.com/wordpress/2023/12/26/%e5%89%8d%e7%ab%af%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%ef%bc%88%e7%82%b9%e5%87%bb%e6%8b%96%e6%8b%bd%ef%bc%89/

欢迎入群一起讨论