0-0.文件上传
0-1.了解文件上传
在前端把本地的 img 视频 音频 之类的文件,发送给服务端,
服务端存储在服务器里面,把文件地址存储在数据库里面
1-0.前端文件上传
1-1. 直接使用 form 表单上传
表单直接上传
form 标签的设置
action 设置服务器地址
method POST 方式
enctype mutilpart/form-data 属性规定在发送到服务器之前应该如何对表单数据进行编码。
=> enctype 设置请求头中的 content-type
=> mutilpart 设置以二进制流的形式上传
input
=> type 选择成 file
=> name 设置一个名字
<form action="http://localhost:8080/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="avatar">
<input type="text" name="username">
<button>上传</button>
</form>
1-2. 原生 JS 上传文件
原生 js 上传
需要用 HTTP/2.0 的技术
一个内置构造函数叫做 FormData()
=> 语法: new FormData(form元素)
=> 返回一个包含 form 元素里面所有带有 name 属性元素的值
=> 直接打印看不到
<form>
<input type="file" name="avatar">
<input type="text" name="username">
<button>上传</button>
</form>
<script>
// 1. 获取元素绑定事件
const form = document.querySelector('form')
form.addEventListener('submit', function (e) {
e.preventDefault()
// 2. 拿到文件
const formData = new FormData(this)
// 3. 正常 ajax 发送
const xhr = new XMLHttpRequest()
xhr.open('POST', '地址')
// 不需要单独设置请求头
// 因为 formData 会自动设置请求头
xhr.send(formData)
xhr.onload = function () {
}
})
</script>
1-3. jQuery 上传文件
jquery 上传和原生 js 基本一致
绑定事件
使用 FormData() 拿到数据
使用 $.ajax()
问题
+ formData 会自动设置请求头, 但是 jquery 也会
=> jquery 会默认设置程 application/x-www-form-urlencoded
+ formData 会发送 二进制流 的形式
=> jquery 会把所有的数据给你直接格式化成 key=value&key=value
<form>
<input type="file" name="avatar">
<input type="text" name="username">
<button>上传</button>
</form>
<script src="../../node_modules/jquery/dist/jquery.min.js"></script>
<script>
$('form').submit(function (e) {
e.preventDefault()
const formData = new FormData($('form')[0])
$.ajax({
method: 'POST',
url: 'http://localhst:8080/upload',
data: formData,
contentType: false, // 不要动请求头, 直接上传
processData: false, // 不要管我的数据, 直接上传
success (res) {
console.log(res)
}
})
})
</script>
2-0.后端文件上传
2-1.单文件上传
单文件上传的简单版本
1. 解决跨域问题
+ 下载一个包叫做 cors
2. 接收文件
2-1. 我要准备一个文件夹, 在服务器上
=> 存储上传的文件
2-2. 需要一个插件帮助
=> multer
=> 下载
=> 导入
2-3. 需要使用 multer 配置一个接收器
=> multer({ dest: '你存放文件的路径' })
2-4. 使用接收器去接收文件
=> 哪一个路由需要接收文件, 配置在哪一个路由上
=> 写在路由标识符的后面, 路由处理函数的前面
=> 接收器.single('前端上传的文件的 key')
2-5. 在路由处理函数里面
=> 会在 req 上面多家一个信息叫做 file
=> 就是你上传的文件的信息
注意: 会把你的文件存储起来, 但是没有后缀, 随机命名
// 导入框架
const express = require('express')
// 创建路由表
const router = express.Router()
// 1. 导入 cors 插件
const cors = require('cors')
// 2-2. 导入 multer 插件
const multer = require('multer')
// 2-3. 使用 multer 去生成一个接收其
// 我配置的这个接收器, 将来接收到的文件就直接存储在 指定目录
const fileUpload = multer({ dest: '../uploads/' })
// 创建服务
const app = express()
// 1. 挂载上 cors 就跨域了
app.use(cors())
// 2-4. 在需要的路由上进行配置
router.post('/upload', fileUpload.single('avatar'), (req, res) => {
console.log('接收请求')
console.log(req.file)
})
// 使用路由表
app.use(router)
// 监听端口号
app.listen(8080, () => console.log(8080))
2-2.单文件上传
single 方法是专门接收单文件-------> 一个名称配一个文件
单文件上传的复杂版本
1. 解决跨域问题
下载一个包叫做 cors
2. 接收文件
2-1. 我要准备一个文件夹, 在服务器上
=> 存储上传的文件
2-2. 需要一个插件帮助
=> multer
=> 下载
=> 导入
2-3. 生成一个仓库信息
=> multer.diskDtorage({ 配置 })
=> destitnation: function () {} 设定存储路径
=> filename: function () {} 设定文件名称
=> 返回值: 是一个仓库信息
2-4. 使用 multer 生成一个接收器
=> 接收器里面配置一个仓库信息
=> 语法: multer({ storage: 仓库信息 })
const express = require('express')
const path = require('path')
const router = express.Router()
// 1. 导入 cors 插件
const cors = require('cors')
// 2-2. 导入 multer 插件
const multer = require('multer')
// 2-3. 使用 multer 生成一个仓库信息
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// req, 本次请求信息
// file, 本次请求的文件
// cb, 回调函数, 利用回调函数来设定存储路径
// 第一个参数 null, 表示不要修改我的 二进制流 文件
cb(null, '../uploads/')
},
filename: function (req, file, cb) {
// req, 本次请求信息
// file, 本次上传的文件信息
// cb, 回调函数, 通过回调函数来设定文件名称
// 从 file 信息里面把后缀名拿出来, 前面我们自己拼接随机数
const tmp = path.extname(file.originalname)
cb(null, `avatar_${ new Date().getTime() }-${ Math.random().toString().slice(2) }${ tmp }`)
}
})
// 2-4. 配置接收器, 带有仓库信息
const fileUpload = multer({ storage :storage})
const app = express()
// 1. 挂载上 cors 就跨域了
app.use(cors())
// 2-5. 使用我们配置好的接收其去接收文件
router.post('/upload', fileUpload.single('avatar'), (req, res) => {
console.log('接收请求')
console.log(req.file)
})
app.use(router)
app.listen(8080, () => console.log(8080))
2-3.单名称多文件上传
array 方法是专门接收多文件----> 一个名称配多个文件
单名称多文件上传
1. 解决跨域问题
+ 下载一个包叫做 cors
2. 接收文件
2-1. 我要准备一个文件夹, 在服务器上
=> 存储上传的文件
2-2. 需要一个插件帮助
=> multer
=> 下载
=> 导入
2-3. 生成一个仓库信息
=> multer.diskDtorage({ 配置 })
-> destitnation: function () {} 设定存储路径
-> filename: function () {} 设定文件名称
=> 返回值: 是一个仓库信息
2-4. 使用 multer 生成一个接收器
=> 接收器里面配置一个仓库信息
=> 语法: multer({ storage: 仓库信息 })
2-5. 使用方法发生一些变换
=> single 方法是专门接收单文件
-> 一个名称配一个文件
=> array 方法是专门接收多文件
-> 一个名称配多个文件
=> 在后面的路由处理函数里面就不能接收 req.file
-> file 只是接收单文件
-> files 接收多文件(以一个数组的形式, 里面存储着每一个文件信息)
const express = require('express')
const path = require('path')
const router = express.Router()
// 1. 导入 cors 插件
const cors = require('cors')
// 2-2. 导入 multer 插件
const multer = require('multer')
// 2-3. 使用 multer 生成一个仓库信息
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// req, 本次请求信息
// file, 本次请求的文件
// cb, 回调函数, 利用回调函数来设定存储路径
// 第一个参数 null, 表示不要修改我的 二进制流 文件
cb(null, '../uploads/')
},
filename: function (req, file, cb) {
// req, 本次请求信息
// file, 本次上传的文件信息
// cb, 回调函数, 通过回调函数来设定文件名称
// 从 file 信息里面把后缀名拿出来, 前面我们自己拼接随机数
const tmp = path.extname(file.originalname)
cb(null, `avatar_${ new Date().getTime() }-${ Math.random().toString().slice(2) }${ tmp }`)
}
})
// 2-4. 配置接收器, 带有仓库信息
const fileUpload = multer({ storage })
const app = express()
// 1. 挂载上 cors 就跨域了
app.use(cors())
// 2-5. 使用我们配置好的接收其去接收文件
router.post('/upload', fileUpload.array('avatar'), (req, res) => {
console.log('接收请求')
console.log(req.file)
console.log(req.files)
})
app.use(router)
app.listen(8080, () => console.log(8080))
2-4多名称多文件上传
在后面的路由处理函数里面就不能接收 req.file
-> file 只是接收单文件
-> files 接收多文件(以一个数组的形式, 里面存储着每一个文件信息)
多名称多文件上传
1. 解决跨域问题
+ 下载一个包叫做 cors
2. 接收文件
2-1. 我要准备一个文件夹, 在服务器上
=> 存储上传的文件
2-2. 需要一个插件帮助
=> multer
=> 下载
=> 导入
2-3. 生成一个仓库信息
=> multer.diskDtorage({ 配置 })
-> destitnation: function () {} 设定存储路径
-> filename: function () {} 设定文件名称
=> 返回值: 是一个仓库信息
2-4. 使用 multer 生成一个接收器
=> 接收器里面配置一个仓库信息
=> 语法: multer({ storage: 仓库信息 })
2-5. 使用方法发生一些变换
=> single 方法是专门接收单文件
-> 一个名称配一个文件
=> array 方法是专门接收多文件
-> 一个名称配多个文件
=> fields 方法是专门接收多文件
-> 多个名称配多个文件
=> 在后面的路由处理函数里面就不能接收 req.file
-> file 只是接收单文件
-> files 接收多文件(以一个数组的形式, 里面存储着每一个文件信息)
注意: 涉及到多个名称, 我们要一个一个标志好
const express = require('express')
const path = require('path')
const router = express.Router()
// 1. 导入 cors 插件
const cors = require('cors')
// 2-2. 导入 multer 插件
const multer = require('multer')
// 2-3. 使用 multer 生成一个仓库信息
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// req, 本次请求信息
// file, 本次请求的文件
// cb, 回调函数, 利用回调函数来设定存储路径
// 第一个参数 null, 表示不要修改我的 二进制流 文件
cb(null, '../uploads/' + file.fieldname)
},
filename: function (req, file, cb) {
// req, 本次请求信息
// file, 本次上传的文件信息
// cb, 回调函数, 通过回调函数来设定文件名称
// 从 file 信息里面把后缀名拿出来, 前面我们自己拼接随机数
const tmp = path.extname(file.originalname)
cb(null, `${ file.fieldname }_${ new Date().getTime() }-${ Math.random().toString().slice(2) }${ tmp }`)
}
})
// 2-4. 配置接收器, 带有仓库信息
const fileUpload = multer({ storage })
const app = express()
// 1. 挂载上 cors 就跨域了
app.use(cors())
// 2-5. 使用我们配置好的接收其去接收文件
router.post('/upload', fileUpload.fields([
{ name: 'avatar' },
{ name: 'photo' }
]), (req, res) => {
console.log('接收请求')
console.log(req.file)
console.log(req.files)
})
app.use(router)
app.listen(8080, () => console.log(8080))