HTML5CORE01
目录
前言
一、拖拽上传文件
1.1.文件上传
二、跨域
三、跨域解决方案
四、查看网站接口
五、文件上传服务
总结
前言
HTML5CORE01学习开始
- HTML5 : 目前主流的 HTML 版本, 其中增加了很多新特性
- 例如: 音视频, 网页存储技术 - webStorage
一、拖拽上传文件
- 把 文件拖拽到 浏览器上, 浏览器可以识别到此文件
- 通过上传操作, 把图片传递到服务器进行保存 --
适合 自定义头像
1.1.文件上传
Express 服务器的
multer
模块提供了 处理上传文件的功能搭建 Express 服务器
- 安装node环境, 推荐使用最新的
长期稳定版本
- 查看已安装的node版本, 命令:
node -v
- Node.js
- 设置中国镜像
- 设置中国镜像: npm set registry https://registry.npmmirror.com
- 查看当前镜像: npm get registry
创建文件夹:
my-server
在文件夹下执行初始化命令:
npm init -y
安装模块: express cors uuid multer express-http-proxy
安装失败的原因: 检查中国镜像是否正确
基础代码
const express = require('express') const app = express() app.listen(3000, () => { console.log('服务器已开启!') }) // 指定静态文件夹 app.use(express.static('public')) // 启动服务器有两种方式 // 1. node app.js // -- 每次JS文件有变更, 都要重启服务器才能生效 // 2. 使用 nodemon 模块, 会自动监听文件变更 自动重启服务器 // -- 前提: 全局安装 npm i -g nodemon // -- nodemon app.js
- 启动
- 访问: localhost:3000
二、跨域
- 典型的跨域报错, 报错关键词:
CORS
,Access-Control-Allow-Origin
- 跨域: 跨越域名的访问
- 在网页中, 利用 JS 向 服务器 请求数据, 要求必须是同一个服务器
- 3个相同: 域名 协议 端口号
协议://域名:端口号
例如 http://localhsot:3000- 开发网站的两种方案
- 前后端不分离 --
服务器渲染
- 服务器要承载更多的操作 -- 把数据拼接成HTML
- 曾经的年代 -- 用户的电脑性能差, 把HTML的合并操作让服务器统一完成
- 但是: 随着访问量的变大, 服务器合并HTML的操作 消耗过多的性能
- 前后端分离
- 优点:分担压力 -- 把HTML的拼接操作 分担给每个用户自己完成
- 跨域场景
- 进一步的分担服务器压力
- 之前的场景模拟中
- live server的 127.0.0.1:5500 相当于A服务器
- localhost:3000/names 相当于B服务器
- 比喻:
- 你在 京东买了个 华为的笔记本电脑, 电脑出问题了
- 你到 淘宝的华为专卖店 找人家维修, 跨域报错
三、跨域解决方案
常见的解决方案有3种:
- CORS --
最推荐
由服务器来进行解决, 服务器安装cors模块即可
原理: 通过请求头, 告诉浏览器
此次访问是安全可靠的
即可类似于: 京东买电脑 到淘宝维修 -- 淘宝店铺声明: 我和京东是同一个商铺
const express = require('express') const cors = require('cors'); const app = express() // 加载 cors 模块, 解决跨域 app.use(cors())
- 白名单模式
const express = require('express') const cors = require('cors'); const app = express() // 加载 cors 模块, 解决跨域 // 默认: 允许所有来源的访问 // app.use(cors()) // 白名单模式: 指定允许的访问来源 app.use(cors({ // ctrl+F5: 刷新网页, 可以清空缓存 origin: ['http://127.0.0.1:3000', 'http://localhost:5500'] })) app.listen(3000, () => { console.log('服务器已开启!') }) // 指定静态文件夹 app.use(express.static('public')) // 启动服务器有两种方式 // 1. node app.js // -- 每次JS文件有变更, 都要重启服务器才能生效 // 2. 使用 nodemon 模块, 会自动监听文件变更 自动重启服务器 // -- 前提: 全局安装 npm i -g nodemon // -- nodemon app.js // // 数据接口: 通常用来与数据库进行交互 app.get('/names', (req, res) => { res.send(['凯凯', '泡泡', '亮亮', '铭铭']) })
- PROXY: 代理模式
- 适合 无法给服务器添加
CORS
的场景, 用于临时解决跨域问题
- 创建
proxy-server
文件夹- 初始化:
npm init -y
安装模块:
npm i express cors express-http-proxy
const express = require('express'); const cors = require('cors'); const proxy = require('express-http-proxy'); const app = express() app.use(cors()) // https://m.douyu.com/api/cate/recList // 访问 localhost:3000/dy app.use('/dy', proxy('https://m.douyu.com')) // 访问 localhost:3000/baidu // 请求到 百度首页的 代码 app.use('/baidu', proxy('https://www.baidu.com')) // nodemon app.js app.listen(3000, () => { console.log('服务器已开启') })
- JSONP
- 利用脚本script 的 src 不跨域的特征, 来解决跨域问题
四、查看网站接口
- 前提: 网站属于前后端分离项目, 通过
AJAX
发送请求- 通过浏览器后台提供的
网络
功能, 可以查看网站发送的所有接口地址
五、文件上传服务
服务器创建
- 文件夹:
upload-server
- 初始化:
npm init -y
- 模块安装:
npm i express cors multer uuid
const express = require('express'); const cors = require('cors'); // multer: 负责处理上传文件 const multer = require('multer'); // uuid: 用于生成唯一名称 const uuid = require('uuid'); const app = express() app.use(cors()) // 静态文件夹: 代表可以通过服务器访问的 app.use(express.static('public')) // 允许通过服务器访问 保存上传文件的文件夹 app.use(express.static('upload')) // nodemon app.js app.listen(3000, () => { console.log('服务器已开启'); }) // 初始化文件上传操作 const upload = multer({ // 配置项 -- ctrl + i 弹提示 // destination: 目标, 目的地 // 设置 上传文件 要保存到的目录 // dest 指定存放的目录, 其他设定都按照默认设定处理 -- 不够人性化 // dest: 'upload' // storage: 可以详细的对上传文件进行自定义设置 storage: multer.diskStorage({ destination: 'upload', // 存放的位置 // 携带3个参数 // req: 请求的信息 // file: 当前上传文件的信息 // cb: callback缩写, 回调函数 -- 用于返回要存放到upload文件夹下的文件名 filename(req, file, cb) { console.log('file', file) // 参数1: 代表是否有错误, null--没有 // 参数2: 代表存放到upload中的文件名 // 缺点: 直接用文件名, 会带来两个问题 // 1. 中文会乱码 // 2. 同名会覆盖 // cb(null, file.originalname) // 截取原文件名中的后缀名部分, 例如 .jpg .png .txt // 最后一个 . 的序号 var dian_index = file.originalname.lastIndexOf('.') // substr: 从指定序号开始截取字符串 var ext = file.originalname.substr(dian_index) // uuid.v4 : 第4种生成唯一标识的方案, 最常用 cb(null, uuid.v4() + ext) } }) }) // 接收单文件上传的接口 // 1. 接收post请求 // 2. upload.single : 代表接收单文件上传 // 3. 'avatar' 指定接收的 参数名 // -- <input type="file" name="avatar" /> app.post('/upload', upload.single('avatar'), (req, res) => { // req: request -- 存放请求时传递的值 // req.file : 代表文件的信息 console.log(req.file) res.send(req.file) })
Form方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上传</title> </head> <body> <h1>欢迎使用 文件上传</h1> <!-- 文件上传: 分 form表单 和 DOM 两种方案 --> <!-- 1. 必须 POST 请求方式 --> <!-- 2. 编码类型, 必须是 multipart/form-data --> <!-- 3. action : 代表提交的接口地址 --> <!-- 4. target : 提交后的信息 显示在哪里 --> <form target="msg" action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="avatar" id=""> <button>上传</button> </form> <!-- 利用 iframe 指定上传后的信息显示位置 --> <!-- 可以隐藏 iframe, 达到隐藏信息的效果 --> <iframe frameborder="1" name="msg" style="display: none;"></iframe> <!-- 不要用 live server, 自带热更新 会导致结果消失 --> <!-- 用 localhost:3000 访问 --> </body> </html>
DOM方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DOM方式上传文件</title> <style> .percent { width: 300px; height: 30px; border-radius: 6px; overflow: hidden; background-color: #eee; } .percent>div { background-color: orange; height: 100%; width: 0; transition: 0.2s; } </style> </head> <body> <div id="box"> <input type="file" name="avatar" id=""> <button>上传</button> </div> <img src="" alt="" height="300"> <div class="percent"> <div></div> </div> <script src="./jquery-3.6.1.min.js"></script> <script> $('#box>button').click(function () { // JQ封装了两个简单的方法: $.get() 和 $.post() 适合处理数据相关的请求 // 读取文件选择标签中的文件信息, 组合成 Form 表单类型的数据 var files = $(this).prev().prop('files') console.log(files) // 关于对 准备上传的文件 的检查 if (files.length == 0) { alert("请选择文件后, 再上传") return } // 超过2m // 1KB = 1024 Byte // 1MB = 1024 KB if (files[0].size > 2 * 1024 * 1024) { alert("文件大小不允许超过2MB") return } // 文件类型只允许图片 // type 中包含 image 字符 // indexOf : 查找指定字符 在字符串中的序号 if (files[0].type.indexOf('image') == -1) { alert("只支持图片类型的文件!") return } var fd = new FormData() // form表单类型的数据格式 fd.append('avatar', files[0]) // 文件上传需要使用 更加自定义的 ajax 方式 $.ajax({ // ctrl+i :查看配置项 url: 'http://localhost:3000/upload', //接口地址 type: 'post', // 请求方式 data: fd, //发送的数据 contentType: false, // 不允许更改 数据的内容类型; 默认会自动改成文本 processData: false, // 不允许对数据自动编码, 默认会把数据当做文本编码 success(res) { console.log('上传完毕:', res) // filename: 保存在 upload 文件夹中的文件名 $('img').prop('src', `http://localhost:3000/${res.filename}`) }, // xhr: 可以监听网络操作的过程 xhr() { var xhr = new XMLHttpRequest() // upload: 监听上传过程 // progress: 上传进度变化时, 触发的事件 xhr.upload.addEventListener('progress', e => { // console.log(e) // 总大小 当前已加载大小 const { total, loaded } = e // 计算出完成的百分比 var percent = (loaded / total).toFixed(2) * 100 + '%' console.log(percent); $('.percent>div').css('width', percent) }) return xhr } }) }) </script> </body> </html>
总结
HTML5CORE01学习结束