上传图片的需求场景
- 用户头像
- 封面图片
- 问题和回答中的图片
- 话题图片
- 等等…
上传图片的功能点
基础功能: 上传图片, 生成图片链接
这两个必须有
上传图片功能: 可以把浏览器和客户端的图片上传到服务端保存
生成图片链接: 可以把图片链接返回给客户端渲染出来
附加功能: 限制图片大小与类型, 生成高中低分辨率图片链接, 生成 CDN
上传图片的技术方案
生产环境:
推荐阿里云 OSS 等云服务, 功能多且稳定
直接上传到服务器, 不推荐在生产环境下使用. 且分布式不友好
使用 koa-body 中间件获取上传的文件
koa-body, 替换 koa-bodyparser
为什么替换, 因为 koa-bodyparser 只支持 json 和 form 两种格式请求体
不支持文件这种格式,
前者支持的格式多
1.安装koa-body
npm i koa-body --save
2.设置图片上传目录
//首先设置
app.use(koaBody({
multipart: true, //设置支持文件格式
formidable: {
//这是个 node 包, 设置一下选项
uploadDir: path.join(__dirname,'/public/uploads'), //设置上传目录
keepExtensions: true, //设置文件后缀名保留
}
}))
3.编写上传接口
//先编写控制器
upload(ctx) {
const file = ctx.request.files.file;
ctx.body = {
path: file.path }
}
//再编写路由
router.post('/upload',upload)
4.生成图片链接
//安装 koa-static 中间件
//该中间件帮助我们生成一个静态服务, 指定了一个文件夹, 文件夹下所有文件可以通过
//http 服务来访问
npm i koa-static --save
app.use(koaStatic(path.join(__dirname), 'public')) //接收的参数就是指定的目录, 然后现在就把图片生成链接了
//接下来在上传接口的控制器里把 path 换成 生成的url
// 如何做呢? 先拿到 basename(文件名加拓展名)
//使用 node 的 path 模块中的 basename 方法
//它接收一个绝对路径并返回 basename
const path = require('path');
upload(ctx) {
const file = ctx.request.files.file;
const basename = path.basename(file.path); //这时拿到的 localhost:端口号/uploads/ 文件名
//但是不可能把这串地址写死进去, 因为部署到服务器要添加域名
//用灵活变量代表
ctx.body = {
url: `${
ctx.origin}/uploads/${
basename}` } //ctx.origin 就是 localhost:端口号
}
编写前端页面上传文件
- 编写上传文件的前端页面
核心就是一个表单, 表单里面有一个可以上传文件的表单项,点击提交
之前搭建了一个静态服务器 public 文件夹下新建一个 html 文件
那么就可以访问这个 html 文件
<!-- action 就是接口, 之前指定的 upload -->
<!-- enctype 代表可以上传文件 -->
<!-- method 是 POST -->
<form action="/upload" enctype="multipart/form-data" method="POST">
<!-- 这种type 的 input,可以让用户选择一个或多个元素提交上传 -->
<!-- 从 file 字段获取文件 -->
<input type="file" name="file">
<button type="submit">点击上传</button>
</form>
用户点击上传成功后返回一个响应体:
{
"url": "http://localhost:端口号/uploads/文件名"
}
如果需要限制上传文件的格式, 在 input 上添加 accept 属性
<input type="file" name="file" accept=".png,.jpeg">
- 与后端接口联调测试