express博客项目上传文件到七牛云

336 阅读3分钟

前言

最近在用express重写博客后端(因为之前的代码实在是太乱了),身边有个专门学后端的同学问我,你图片资源都是保存在哪里的?我直接给他看了我的项目目录,说道:“保存在express的静态web目录下啊”。如下。

image.png

然后他就开始了吐槽,并且给我转发了一篇名为《无语!刚来的实习生竟然把文件上传到本地服务器中》的文章。其实也有道理,如果服务器离用户太远的话,获取资源的速度太慢。所以我考虑将这些资源在请求的时候存储到七牛云上,并且写这篇文章,记录一下。

步骤1:创建七牛云存储空间

image.png

创建完成之后,会给你一个测试外链域名,我们可以上传文件

image.png

并且通过这个外链域名来获取文件

image.png

步骤2:修改外链域名为备案域名

首先创建绑定域名

image.png

其余配置几乎不需要改,这里的域名是已经备案的域名,如果是存图片文件的话,一般将test前缀改成img

image.png

添加成功之后进入域名管理,新添加的域名状态为成功时才可以使用,并且刚添加的域名是未配置的,我们需要配置CNAME

image.png

鼠标移入未配置,复制对应的地址,进入域名服务器进行配置(我是腾讯云)。如下,记录值是刚才赋值的地址。

image.png

配置完之后回到七牛云域名管理,刷新看对应的域名是否是已配置状态

image.png

如果是已配置,并且状态是成功,那么回到存储空间的文件管理中,外链域名会新增一条(就是刚才添加的那条),选中它即可。

步骤3:使用multer和qiniu这两个库实现上传文件

npm install multer qiniu

请求入口如下

  • auth是我自己写的登录认证中间件,可以不用管
  • 第二个是multer的使用方法,这里的作用是将req.body中携带的files对应的文件解析,保存在req.file中
  • Upload中间件是实现上传的中间件

image.png

请求如下,title是文章名,categoryName是分类名,用于实现开头的分文件管理图片的效果

image.png

Upload中间件的实现

在使用qiniu这个库之前,我们需要做一些前置操作:创建配置信息。

image.png

AK和SK用于登录并且获取操作七牛云的权限,bucket是对应的存储空间的名字,AK和SK的获取方法在下图。

image.png

Upload中间件代码如下

//传入AK和SK
const mac = new qiniu.auth.digest.Mac(qiniuConfig.AK, qiniuConfig.SK);

const config = new qiniu.conf.Config();
config.zone = qiniu.zone.Zone_z2;  //选择地区,这取决于存储空间所在的区域

const putPolicy = new qiniu.rs.PutPolicy({
  scope: qiniuConfig.bucket,  //存储空间名字
  expires: 7200,
  callbackBodyType: "application/json",
});
const uploadToken = putPolicy.uploadToken(mac);

const formUploader = new qiniu.form_up.FormUploader(config);
const putExtra = new qiniu.form_up.PutExtra();

let Upload = (req, res) => {
  //获取文章名 和 分类名
  const { title, categoryName } = req.body;
  const buffer = req.file.buffer; // 获取buffer

  formUploader.put(
    uploadToken,
    `img/${categoryName}/${title}/${req.file.originalname}`,  //保存的路径
    buffer,  //传入文件buffer
    putExtra,
    function (respErr, respBody, respInfo) {  //回调函数
      if (respErr) {
        throw respErr;
      }
      if (respInfo.statusCode == 200) {
        res.send(respBody);
      } else {
        res.send({
          status: respInfo.statusCode,
          respBody,
        });
      }
    }
  );
};

对上面代码的部分解释

  • 关于config.zone的值,需要查看存储空间的区域,选择对应的值

image.png

image.png

  • 因为我需要做到分文件存储/img/分类名/文章名/对应的图片文件,所以需要在请求中传入title和categoryName。实现的效果如下。

image.png

image.png

另外,通过上图可以看到,返回的信息中key值是对应的文件目录,我们只需要拼接上外链域名就是图片地址啦。