eggjs 怎么实现上传图片(头像)接口功能?

Posted 凯小默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eggjs 怎么实现上传图片(头像)接口功能?相关的知识,希望对你有一定的参考价值。

在实现上传接口的时候,需要了解一下上传的过程跟需要依赖的库,以及测试上传需要注意的问题。这里顺便说一下,注册的时候去掉默认的图片头像了,还有默认的签名。

图片上传到服务器的逻辑

  1. 首先前端调用上传接口,将上传的资源经过 FormData 实例封装之后,传给服务端
  2. 在服务端接收前端传进来的图片信息,通过 fs.readFileSync 方法,来读取图片内容,并存放在变量中
  3. 找个存放图片的公共位置
  4. 通过 fs.writeFileSync 方法,将图片内容写入公共位置
  5. 最后返回图片地址

依赖的库

需要对:fsmomentpathmkdirp,有一定了解,fs,path 大家应该比较熟悉了,这里就对 moment 以及 mkdirp 做一下简单的介绍,具体的可以查看文档:

mkdirp

mkdirp 是一款在 node.js 中像 mkdir -p 一样递归创建目录及其子目录。

安装

npm install -g mkdirp

使用

var mkdirp = require('mkdirp');
    
mkdirp('/tmp/foo/bar/baz', function (err) 
    if (err) console.error(err)
    else console.log('kaimo')
);
// 输出 kaimo,/tmp/foo/bar/baz 目录就会出现。

moment

Moment.js 是一个轻量级的 javascript 时间库,它方便了日常开发中对时间的操作,提高了开发效率。

安装

npm install moment

使用

var moment = require('moment');
moment().format();
// 格式化日期时间
moment(value).format('YYYY-MM-DD HH:mm:ss');

// moment(Date):可以使用预先存在的原生 Javascript Date 对象来创建 Moment。
var day = new Date(2011, 9, 16);
var dayWrapper = moment(day);
// 这会克隆 Date 对象,Date 的后续更改不会影响 Moment,反之亦然。

eggjs 里文件上传接收

egg 获取上传文件的方法中官方给了两种处理方法:这里采用用 file 直接读取

  1. file 直接读取
  2. stream 流的方式:创建文件写入流,以管道方式写入流

file 读取方式

需要先在 config.defult.js 里配置:

config.multipart = 
  mode:'file'
;

控制层代码:

// file 包含了文件名,文件类型,大小,路径等信息
// files[0]表示获取第一个文件,若前端上传多个文件则可以遍历这个数组对象
let file = ctx.request.files[0]
// 读取文件 
let filedata = fs.readFileSync(file.filepath);
// 将文件存到指定位置
fs.writeFileSync(path.join('./', `uploadfile/test.png`), filedata)

关于 stream 流的方式可以参考:【egg文件上传接收总结】

上传接口实现

0、配置

需要先在 config.defult.js 里配置:文件读取配置,以及上传头像路径,我们单独把头像放到本地的 kaimo-cost-images 文件夹里,跟项目分开,就不放到app的public文件夹里了,这个不需要手动去 D 盘创建文件夹,到时会自动生成的。

// add your user config here
const userConfig = 
  // myAppName: 'egg',
  uploadAvatarDir: 'D://kaimo-cost-images/images/avatar', // 上传头像路径
;
// 文件读取配置
config.multipart = 
  mode: 'file'
;

1、新建路由

配置完,开始去 router.js 文件里写一下请求上传的路由

// 上传头像
router.post('/api/upload/avatar', verify_token, controller.upload.uploadAvatar);

2、新建 upload.js 文件

在 controller 文件夹下新建 upload.js 用于处理上传的相关逻辑

3、编写上传逻辑

  1. 获取文件,ctx.request.files[0]表示获取第一个文件,若前端上传多个文件则可以遍历这个数组对象
  2. 获取当前日期
  3. 创建图片保存的路径
  4. 创建目录
  5. 生成路径返回
  6. 写入文件夹
  7. 清除临时文件,ctx.cleanupRequestFiles();
'use strict';
const fs = require('fs');
const path = require('path');
const moment = require('moment');
const mkdirp = require('mkdirp');

const Controller = require('egg').Controller;

class UploadController extends Controller 
  async uploadAvatar () 
    const  ctx, config  = this;
    try 
      // 0、获取文件
      let file = ctx.request.files[0];
      console.log('获取文件', file);
      // ctx.request.files[0] 表示获取第一个文件,若前端上传多个文件则可以遍历这个数组对象
      let fileData = fs.readFileSync(file.filepath);
      console.log('fileData', fileData);
      // 1、获取当前日期
      let day = moment(new Date()).format('YYYYMMDD');
      console.log('1、获取当前日期', day);
      // 2、创建图片保存的路径
      let dir = path.join(config.uploadAvatarDir, day);
      console.log('2、创建图片保存的路径', dir);
      // 3、创建目录
      await mkdirp(dir);
      // 4、生成路径返回
      let date = Date.now(); // 毫秒数
      let tempDir = path.join(dir, date + path.extname(file.filename)); // 返回图片保存的路径
      console.log('毫秒数 extname', date, path.extname(file.filename));
      console.log('返回图片保存的路径', tempDir);
      // 5、写入文件夹
      fs.writeFileSync(tempDir, fileData);
      ctx.body = 
        status: 200,
        desc: '上传成功',
        data: tempDir,
      
     catch(error) 
      ctx.body = 
        status: 500,
        desc: '上传失败',
        data: null
      
     finally 
      // 6、清除临时文件
      ctx.cleanupRequestFiles();
    
  


module.exports = UploadController;

测试接口

还是老样子,先登录,然后拿到 token,在上传一张图片,比如我选择一只修勾勾,然后点击发送。

我们可以看到成功返回了图片所在的路径。当然实际项目里不会返回服务器的路径的,下一节我们在优化处理。

接下来,看看 D 盘是否生成了文件夹跟保存了图片。我们发现是保存成功了。

以上是关于eggjs 怎么实现上传图片(头像)接口功能?的主要内容,如果未能解决你的问题,请参考以下文章

eggjs 怎么实现返回 base64 图片的接口给前端回显头像?

java web实现上传头像功能,

eggjs 怎么实现用户注册功能?

eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?

完美实现类似QQ的自拍头像上传头像功能!(Demo 源码)

eggjs 怎么使用 egg-jwt 进行用户鉴权实现登录功能?