koa实现简单图片上传

搭建koa基础结构

  1. 新建一个文件夹
  2. 执行npm init -y
  3. 安装koa koa-router
npm install koa koa-router --save
  1. 新建app.js引入:
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()

// 路由写在最下面
app.use(router.routes())
app.use(router.allowedMethods())  // 允许http请求的所有方法

app.listen(3000, (ctx) => {
  console.log('服务开启在三千端口')
})
  1. 开启服务:
    执行node app.js,命令行打印'服务开启在三千端口'表示开启成功,因为是最简单的搭建,改了任何东西都要重新执行 node app.js

编写和引入路由

  1. 根目录新建route文件夹,新建index.js
  2. 编写index.js:
const Router = require('koa-router')
const router = new Router()

router.get('/', async (ctx, next) => {
  ctx.body = ctx.request
})

module.exports = router
  1. app.js中引入,写在app.use(router.routes())的上面:
....
const index = require('./route/index')
/**
这里可以写成app.use('/', index.routes())
第一个参数代表这个文件路由的前缀,访问时就得加上设置的前缀
*/
router.use(index.routes())

app.use(router.routes())
app.use(router.allowedMethods())  // 允许http请求的所有方法
...
  1. 此时访问localhost:3000:


    image.png

处理post请求参数

文件上传请求肯定是post请求,koa中处理post请求参数需要安装一个中间件

  1. 安装koa-body
npm install koa-body --save
  1. app.js中引入和使用:
...
const koaBody = require('koa-body')

// 接收post参数解析,写在路由的前面
app.use(koaBody({
  multipart: true
}))

// userouter
...

我们处理文件上传需要在koaBody的配置设置multipart 为 true,这样上传的文件也就是formdata,会被koaBody处理在ctx.request.files中,其他普通的参数通过ctx.request.body就可以拿到:

拿文件:
const file = ctx.request.files['上传文件的字段名']

普通参数:
const data = ctx.request.body

编写上传接口与前端代码

  1. 在route文件夹下新建一个upload.js,假设规定上传的文件字段名叫file,假设只上传一个文件:
const Router = require('koa-router')
const router = new Router()

router.post('/upload', async (ctx, next) => {
  const { name, path: filePath, size, type } = ctx.request.files.file
  ctx.body = {
    name, // 文件名称
    filePath, // 临时路径
    size, // 文件大小
    type // 文件类型
  }
})

module.exports = router

上传的文件会包含上面那个几个字段,其中path为临时路径,把他们返回,下面会把接口请求结果贴出来,看一下就知道各个字段的含义。

  1. app.js中引入路由与处理跨域
    因为在本地模拟,前端我会直接写一个html文件,所以会出现跨域,这里顺便解决一下
npm install koa-cors --save

app中引入并使用:

// 放在最前面
const cors = require('koa-cors')
app.use(cors({
  origin: '*'
}))

引入upload路由:

const upload = require('./route/upload')
router.use(upload.routes())
  1. 前端代码:

  
  

  

这里用了原生的ajax,返回的response是个json字符串

  1. 发送请求以及返回数据
    当我选择一个文件并点击上传后:
    image.png

    可以看到,在koa接口返回的数据这里都能正常展示,上面说到在router中,通过ctx.request.files.file拿到的path是临时路径,现在应该明确了吧,可以看到这个路径是存在我们电脑保存临时文件的地方,我们直接访问这个路径就是我们刚上传的图片,也就是说前端上传文件,在我们处理之前,koa会把我们的文件放在一个临时目录上,文件信息会放在ctx.request.files上,这时候我们只要把文件转移到我们想要的地方就可以。
  2. 移动文件
    上面说到要把文件从临时目录移动到我们想存储的地方,移动文件可以用node原生的fs模块,这里我用一个fs的拓展库:fs-extra,操作起来比较方便,api也很简单。fs-extra文档

安装: npm install fs-extra --save

改一下我们的upload接口,upload.js:

const Router = require('koa-router')
const router = new Router()
const path = require('path')
const fse = require('fs-extra')

router.post('/upload', async (ctx, next) => {
  const { name, path: filePath, size, type } = ctx.request.files.file
  const dest = path.join(__dirname, '../upload', name) // 目标目录,没有没有这个文件夹会自动创建
  await fse.move(filePath, dest) // 移动文件
  ctx.body = {
    name, // 文件名称
    filePath, // 临时路径
    size, // 文件大小
    type // 文件类型
  }
})

module.exports = router

然后我们重新上传一下文件

image.png

上传成功后,在我们koa项目的文件夹中,会自动多出来一个upload文件夹,里面就有我们上传的图片:
image.png

然后我们复制返回的filepath,也就是文件上传后的临时路径:
image.png

可以看到存在我们电脑临时目录下的文件就被移动走,相当于删除。

koa处理静态资源

其实上面已经实现了图片上传并且保存到我们想要的位置,那怎么访问呢,前端怎么展示呢,这就需要处理静态资源了。

  1. koa-static安装与使用
npm install koa-static --save

在app.js中:

const koaStatic = require('koa-static')

// 填上我们存放图片文件路径
app.use(koaStatic(path.join(__dirname, './upload/')))

这时候我们就可以直接通过图片的文件名访问图片了,我们上面上传的一张图片叫girl.jpg,这时候直接访问:

image.png

  1. 返回url与前端展示
    可以看到图片可以直接展示了,所以我们这时候只需要把图片的名称返回给前端就可以,把接口修改一下,此时访问图片的url就是图片的名称,当然看你们具体的逻辑,如果上面保存图片保存在../upload/img/xxx.jpg,那么访问图片的url就变成/img/xxx.jpg
router.post('/upload', async (ctx, next) => {
  const { name, path: filePath, size, type } = ctx.request.files.file
  const dest = path.join(__dirname, '../upload', name) // 目标目录,没有没有这个文件夹会自动创建
  await fse.move(filePath, dest) // 移动文件
  ctx.body = {
    name, // 文件名称
    filePath, // 临时路径
    size, // 文件大小
    type, // 文件类型
    url: name
  }
})

前端加个img标签展示图片:


  
  
  

  

前端上传后:


image.png

添加参数

如果需要添加其他参数,就在formdata中再append其他参数

  1. 前端添加参数
...
var formdata = new FormData()
formdata.append("file", file)
// 传其他参数
formdata.append("other", "test")
...
  1. 后端处理其他参数:
router.post('/upload', async (ctx, next) => {
  const { name, path: filePath, size, type } = ctx.request.files.file
  const dest = path.join(__dirname, '../upload', name)
  await fse.move(filePath, dest, { overwrite: true })
  ctx.body = {
    name, // 文件名称
    filePath, // 临时路径
    size, // 文件大小
    type, // 文件类型
    url: name,
    data: ctx.request.body // 其他参数,会自动过滤file
  }
})

这时候把ctx.request.body返回给前端,看看是什么样的:

image.png

可以看到 ctx.request.body 会自动过滤掉上传的文件参数,通过这个我们就可以拿到其他普通的参数,这个逻辑和一些框架中的上传组件是一样的。

到这里整个功能就实现了,欢迎大家指教哦。

你可能感兴趣的:(koa实现简单图片上传)