文件上传
Galloping_Leo 2020-02-20 node基础模块
# 文件上传
# 一、二进制文件上传
# 选择的图片即时预览+文件上传
# 单张图片即时预览+文件上传+formidable
使用FileReader
构造函数实例化一个文件读取对象reader
,在调用reader.readAsDataURL()
方法读取选择的文件,最后在onload
事件触发时(文件加载完成时),可在会调函数中通过reader.result
得到文件的读取结果,最后将img
标签的src
属性设置为读取的结果即可显示图片。
客户端
var formData = new FormData()
//选择文件,即时预览
file.onchange = function () {
formData.append('attrName', this.files[0])
//创建文件读取对象
var reader = new FileReader()
//用户选择的文件列表
//this.files
//读取文件,异步方法,不能通过返回值的形式得到结果
reader.readAsDataURL(this.files[0])
//文件读取完成,监听onload,得到文件读取结果
reader.onload = function () {
console.log(reader.result)
preview.style.width = '250px'
preview.style.border = '1px solid #cbcbcb'
//将文件读取的结果显示到页面上
preview.src = reader.result
}
}
//点击实现上传
btn.onclick = function () {
if (formData.get('attrName')) {
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://localhost:3000/upload')
xhr.send(formData)
xhr.onload = function () {
if (xhr.status == 200) {
console.log(xhr.responseText)
}
}
} else {
window.alert('请选择图片!')
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
后台
// 引入express框架
const express = require('express');
// 路径处理模块
const path = require('path');
const promisify = require('util').promisify
const formidable = require('formidable');
const fs = require('fs')
const renameFile = promisify(fs.rename)
const app = express();
app.post('/upload', (req, res) => {
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// 设置客户端上传文件的存储路径
form.uploadDir = path.join(__dirname, 'public', 'uploads');
// 保留上传文件的后缀名字
form.keepExtensions = true;
// 解析客户端传递过来的FormData对象
form.parse(req, async (err, fields, files) => {
let oldpath = files.attrName.path
let newpath = path.join(__dirname, 'public', 'uploads', files.attrName.name)
const renameFile = promisify(fs.rename)
try {
//文件重命名
await renameFile(oldpath, newpath)
} catch (error) {
console.log('错误!')
}
console.log('成功!')
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 多张图片即时预览+上传文件+文件重命名
核心方法:使用 window.URL.createObjectURL
获取文件在本地的路径,需要一个文件对象作为参数。
图片展示容器
<div class="padding" id="box">
</div>
1
2
3
2
3
图片模板文件
<script id="tpl" type="text/html">
{{each srcs}}
<img src="{{$value}}" class="img-rounded img-responsive" id="preview">
{{/each}}
</script>
1
2
3
4
5
2
3
4
5
js
var formData = null
file.onchange = function () {
//this.files 是用户所选择的文件 伪数组。
formData = new FormData
let srcArr = []
for (var i = 0; i < this.files.length; i++) {
formData.append(`file${i}`, this.files[i])
//获取路径
var src = window.URL.createObjectURL(this.files[i])
//加入到路径数组
srcArr.push(src)
}
//渲染模板,传入路径模板
var html = template('tpl', { srcs: srcArr })
//廷加到DOM结构中
document.getElementById('box').innerHTML = html
}
btn.onclick = function () {
if (formData && formData.has('file0')) {
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://localhost:3000/upload')
xhr.send(formData)
xhr.onload = function () {
if (xhr.status == 200) {
console.log(xhr.responseText)
}
}
} else {
window.alert('请选择图片!')
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
后台
// 引入express框架
const express = require('express');
// 路径处理模块
const path = require('path');
const promisify = require('util').promisify
const formidable = require('formidable');
const fs = require('fs')
const renameFile = promisify(fs.rename)
const app = express();
app.post('/upload', (req, res) => {
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// 设置客户端上传文件的存储路径
form.uploadDir = path.join(__dirname, 'public', 'uploads');
// 保留上传文件的后缀名字
form.keepExtensions = true;
// 解析客户端传递过来的FormData对象
form.parse(req, async (err, fields, files) => {
console.log(files)
for (let f in files) {
let oldpath = files[f].path
let newpath = path.join(__dirname, 'public', 'uploads', files[f].name)
try {
await renameFile(oldpath, newpath) //重命名文件
} catch (error) {
console.log('错误!')
}
}
res.send('ok')
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 后台返回地址图片即时预览
先将文件上传到服务器,再由后端返回给前端图片地址,然后前端创建 img
标签设置 src
属性
客户端核心代码
xhr.onload = function () {
var responseText = JSON.parse(xhr.responseText)
var img = document.createElement('img')
img.src = responseText.src
img.onload = function () {
box.appendChild(img)
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
后端核心代码
// 实现文件上传的路由
app.post('/upload', (req, res) => {
// 创建formidable表单解析对象
const form = new formidable.IncomingForm();
// 设置客户端上传文件的存储路径
form.uploadDir = path.join(__dirname, 'public', 'uploads');
// 保留上传文件的后缀名字
form.keepExtensions = true;
// 解析客户端传递过来的FormData对象
form.parse(req, async (err, fields, files) => {
let oldpath = files.attrName.path
let newpath = path.join(__dirname, 'public', 'uploads', files.attrName.name)
try {
await renameFile(oldpath, newpath)
} catch (error) {
console.log('错误!')
}
res.send({src: path.join('/uploads', files.attrName.name)})
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 上传进度条
核心代码
绑定xhr.upload.onprogress
事件,该事件在文件上传的过程中会不断的触发,回调函数中有一个事件对象ev
,可以通过ev.loaded
获取已经上传的量,通过ev.total
来获取文件总大小,通过这两个值可以得出上传的百分比,从而设置进度条宽度。
xhr.upload.onprogress = function (ev) {
var result = parseInt((ev.loaded / ev.total) * 1000) / 10 + '%'
bar.innerHTML = result
bar.style.width = result
}
1
2
3
4
5
2
3
4
5