最终效果:
前言
文件上传其实跟上传json对象或者文本差不多,我们需要通过给http的请求头设置对应的Content-type来告诉浏览器我们要上传的类型,常见的就是application/json(处理json对象),text/plain(纯文本)和multipart/form-data(文件上传)
项目搭建
-
新建文件夹
- 初始化npm 项目并下载依赖包
npm init -y
npm i webpack webpack-cli@3 webpack-dev-server html-webpack-plugin formidable
webpack-cli如果不指定版本,有可能跟最新版的webpack不兼容,所以这里指定一下
formidable是用来处理后端接受到的http请求body中的文件数据
- 在根目录下新建webpack.config.js作为webpack的配置文件
//webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
port:8080
},
plugins: [
new HtmlWebpackPlugin({
title: 'ajax上传文件',
template: path.resolve(__dirname, 'index.html')
})
],
}
代码很简单,就是等下把我们前端的源码通过webpack-dev-server打包进内存,并启动一个服务,然后把打包后的文件引入指定的index.html模板中
- 根目录下新建index.html
Document
- 根目录新建src文件,新建文件index.js
;(function () {
let oFileInput = document.getElementById('file')
let oSubmit = document.getElementById('submit')
let file
function init() {
oFileInput.addEventListener("change",function (e) {
file = this.files[0]
})
oSubmit.addEventListener("click",function (e) {
let xhr = new window.XMLHttpRequest()
xhr.open("post","http://localhost:3000",true)
var fd = new FormData()
fd.append("file",file)
xhr.upload.onprogress = function(e){
var value = (e.loaded / e.total * 100).toFixed(1);
console.log(value)
}
xhr.send(fd)
})
}
init()
})()
其中值得说的是FormData,他是一个表单构造函数,通过append方法来增加数据,
跟我们自己写一个html表单来上传文件差不多,只是form是同步的,而且页面会跳转到action,而js实例化显然更自由。
而文件的监听进度利用upload对象的onprogress
- 后端服务
const http = require('http')
const formidable = require('formidable')
const fs = require('fs')
const path = require('path')
const app = http.createServer((req, res) => {
const form = new formidable.IncomingForm()
form.encoding = 'utf-8'
form.uploadDir = './upload'
form.parse(req, function (err, fields, files) {
if (!files.file) return
let oldpath = path.join(__dirname, files.file.path)
let newPath = path.join(__dirname, '/upload', files.file.name)
fs.rename(oldpath, newPath, function (err) {
if (err) {
throw Error('改名失败')
}else{
console.log("保存文件:",newPath)
}
})
})
res.writeHead(200, {
'Content-Type': 'text/html;charset=utf-8', 'Access-Control-Allow-Origin': '*'
})
res.end('哈哈
')
})
app.listen(3000, () => {
console.log('running!!')
})
首先通过http启动一个node服务,通过formidable解析http请求体中的文件数据,最终形成json对象并注入到回调函数中,其中oldPath和newPath是为了修改文件名,因为默认接受到的文件是没有扩展名的,文件无法识别,所以需要我们手动修改一下,最后设置一下跨域头就可以了。