1. 准备工作
因为要发送Ajax请求,而Ajax技术的运行需要网站环境,因此其中一个解决方案是,将页面作为网站的静态资源暴露出来,然后通过浏览器进行访问.
1.1 静态资源
- 使用express将public下面的资源暴露出来
- 在根目录下面新建一个
public
文件夹和一个app.js
文件
// app.js
const express = require('express');
const path = require('path')
const app = express();app.use(express.static(path.join(__dirname, 'public')))app.listen(3000, () =>{console.log('localhost:3000');
})
- 在public下新建一个
01.html
<!-- 01.html -->
<body><h2>通过静态资源访问 01.html</h2>
</body>
- 命令行输入
nodemon app.js
(注意目录), 打开浏览器访问localhost:3000/01.html
2. 文件上传的进度条展示
- 下面的样式使用到了 bootstrap. 不导入也没关系
- 在文件上传的过程中,可以将上传的进度实时展示出来,这样用户的体验感会提升
- 核心代码如下:
file.onchange = function () {xhr.upload.onprogress = function (ev) {console.log( (ev.loaded / ev.total) * 100 + '%' );}
}
- 思路如下:
1.在input框下面有一个显示进度条的元素
2.点击文件上传后,会触发file.onchange
事件
3.在文件传到服务器(FormData
)的过程中会持续触发xhr.upload.onprogress
事件.
4.在onprogress
事件中,会有一个ev
对象,它保留着,文件上传的信息
5.利用文件上传的信息,算出上传的进度,显示在网页中
2.1 [栗子] - 上传的表单控件
<div class="container"><div class="form-group"><label>请选择文件</label><input type="file" id="file" /><br /><div class="progress"><div class="progress-bar" style="width: 0%;" id="bar">0%</div></div></div>
</div>
2.2 [栗子] - 上传的代码(前端)
<script>var file = document.getElementById('file');var bar = document.getElementById('bar');file.onchange = function () {// 文件上传使用到 FormData构造函数var formData = new FormData();// 'attrName'方便后面使用.formData.append('attrName', this.files[0]);// 上传的信息准备好了,接下来准备Ajax请求var xhr = new XMLHttpRequest();xhr.open('post','http://localhost:3000/uploads');// 文件上传的过程中,会持续触发onprogress事件xhr.upload.onprogress = function(ev){var result = (ev.loaded / ev.total) * 100 + '%';// 算出上传的百分比,并将值放在bar中bar.style.width = result;bar.innerHTML = result;}xhr.send(formData);xhr.onload = function () {if(xhr.status == 200 ){console.log(xhr.responseText)}}}
</script>
2.3 [栗子] - 上传的代码(服务端)
// 服务端使用formidable解析参数
const formidable = require('formidable');
const path = require('path')
app.post('/uploads', (req, res)=>{// 创建接收的实例const form = new formidable.IncomingForm();// 设置文件的存储位置form.uploadDir = path.join(__dirname, 'public', 'uploads');// 保留后缀名form.keepExtensions = true;// 解析客户端的数据form.parse(req, (err, fields ,files) =>{res.send({ path: files.attrName.path.split('public')[1] })})
})
3. 文件上传图片即使预览
- 以前写过一篇放在前端内存中的
- 这一篇是:
- 将图片通过
FormData
传递到服务端 - 然后服务端将图片保存在静态资源中,并将资源的地址返回给客户端
- 然后客户端访问这个静态资源进行显示
- 将图片通过
3.1 [栗子] - 前端dom元素如下
<div class="container"><div class="form-group"><label>请选择</label><input type="file" id="file" /><!-- 用来显示上传的图片 --><div class="padding" id="box"></div></div>
</div>
3.2 [栗子] - 前端上传文件的代码
<script>var file = document.getElementById('file');var box = document.getElementById('box');file.onchange = function () {var formData = new FormData();formData.append('attrName', this.files[0]);var xhr = new XMLHttpRequest();xhr.open('post', 'http://localhost:3000/uploads')xhr.send(formData);xhr.onload = function() {if(xhr.status == 200) {var result = JSON.parse(xhr.responseText);var img = document.createElement('img');img.src = result.path;img.onload = function() {box.appendChild(img)}}}}
</script>
3.3[栗子] - 后端代码
// 服务端使用formidable解析参数
const formidable = require('formidable');
const path = require('path')
app.post('/uploads', (req, res)=>{// 创建接收的实例const form = new formidable.IncomingForm();// 设置文件的存储位置form.uploadDir = path.join(__dirname, 'public', 'uploads');// 保留后缀名form.keepExtensions = true;// 解析客户端的数据form.parse(req, (err, fields ,files) =>{res.send({ path: files.attrName.path.split('public')[1] })})
})
4. 参考
源代码