# koa 实现上传图片功能

# 上传图片的需求分析

  • 基础功能:上传图片、生成图片链接
  • 高级功能:限制上传图片的大小与类型、生成高中低三种分辨率的图片链接、生成CDN

# 上传图片的技术方案

阿里云OSS等云服务,推荐生产环境下使用。不要上传到自己的服务器,服务器重启数据容易丢失,且不支持分布式。

  1. koa-body : 相比 koa-bodyparser,不仅支持json形式的params,还支持文件等类型。所以 koa-body 更强大

示例:

const koaBody = require('koa-body');
const Router = require('koa-router');
const path = require('path');
const app = new Koa();
const router = new Router();

router.post('/upload', async(ctx) => {
  const file = ctx.request.files.file;
  ctx.body = {
    path: file.path
  };
})

app.use(koaBody({
  multipart: true, // 允许文件上传
  formidable: {
    uploadDir: path.join(__dirname, '/public/uploads'),
    keepExtensions: true,  // 扩展名
  }
}))

上面代码将文件上传到服务器目录 /public/uploads 文件夹下了。但是如何生成链接访问呢?这时就需要koa-static

koa-static 提供了一套静态服务机制,可以让我们通过路由访问服务器中的资源。

使用koa-static的步骤:

  1. 安装 koa-static
  2. 设置静态文件目录
  3. 生成图片链接

示例:

const koaBody = require('koa-body');
const koaStatic = require('koa-static');
const Router = require('koa-router');
const path = require('path');
const app = new Koa();
const router = new Router();

router.post('/upload', async(ctx) => {
  const file = ctx.request.files.file; 
  const basename = path.basename(file.path); // file.path这个是服务器的绝对路径
  ctx.body = {
    url: `${ctx.origin}/uploads/${basename}`
  };
})

app.use(koaStatic(path.join(__dirname, 'public')))

app.use(koaBody({
  multipart: true, // 允许文件上传
  formidable: {
    uploadDir: path.join(__dirname, '/public/uploads'),
    keepExtensions: true,  // 扩展名
  }
}))

然后编写前端页面进行测试:

<form action="/upload" enctype="multipart/form-data" method="POST">
  <!-- accept="image/png" | accept=".png": 只允许上传png文件 -->
  <!-- accept="image/png,image/jpeg" | accept=".png,.jpeg": 允许上传png, jpeg文件 -->
  <!-- accept="image/*: 通配符 -->
  <input type="file" name="file" accept="image/png"> 
  <button type="submit">上传</button>
</form>