eggjs 怎么实现上传图片(头像)接口功能?
Posted 凯小默
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eggjs 怎么实现上传图片(头像)接口功能?相关的知识,希望对你有一定的参考价值。
在实现上传接口的时候,需要了解一下上传的过程跟需要依赖的库,以及测试上传需要注意的问题。这里顺便说一下,注册的时候去掉默认的图片头像了,还有默认的签名。
图片上传到服务器的逻辑
- 首先前端调用上传接口,将上传的资源经过 FormData 实例封装之后,传给服务端
- 在服务端接收前端传进来的图片信息,通过
fs.readFileSync
方法,来读取图片内容,并存放在变量中 - 找个存放图片的公共位置
- 通过
fs.writeFileSync
方法,将图片内容写入公共位置 - 最后返回图片地址
依赖的库
需要对:fs
、moment
、path
、mkdirp
,有一定了解,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 直接读取
- file 直接读取
- 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、编写上传逻辑
- 获取文件,
ctx.request.files[0]
表示获取第一个文件,若前端上传多个文件则可以遍历这个数组对象 - 获取当前日期
- 创建图片保存的路径
- 创建目录
- 生成路径返回
- 写入文件夹
- 清除临时文件,
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 图片的接口给前端回显头像?