Laf结合七牛云对象存储轻松实现文件上传

一、什么是七牛云?

七牛云是国内领先的以视觉智能和数据智能为核心的企业级云计算服务商,同时也是国内知名智能视频云服务商,累计为 70 多万家企业提供服务,覆盖了国内80%网民。围绕富媒体场景推出了对象存储、融合 CDN 加速、容器云、大数据平台、深度学习平台等产品、并提供一站式智能视频云解决方案。为各行业及应用提供可持续发展的智能视频云生态,帮助企业快速上云,创造更广阔的商业价值。
简而言之就是一家提供网上存储的服务商,实名认证可以获取10G免费空间,对于小型网站存储图片文档已经够了,最主要的是可以减轻你服务器的压力,加快网页加载速度,隐藏真实IP等,好处不用多说,直接上教程。

二、前期准备

1.七牛云注册
进入七牛云官网进行注册,地址:https://www.qiniu.com/
在这里插入图片描述
2.获取密钥
完成注册后登录七牛云并进入控制台,在右上角头像处下拉选择【密钥管理】获取AccessKey和SecretKey
在这里插入图片描述
3.新建空间
选择【对象存储】下的【空间管理】,点击“新建空间”按钮
在这里插入图片描述
完成后点击“空间名称”会跳转到“空间概览”界面,如下图:
在这里插入图片描述
域名管理:若需要接入自己已备案好的域名,可以在【域名管理】中进行配置,具体如何配置可参考链接 https://developer.qiniu.com/fusion/1322/how-to-configure-cname-domain-name
在这里插入图片描述
在这里插入图片描述

三、在Laf中接入七牛云

登录Laf云开发平台,在应用列表中选择一个应用后点击【开发】按钮,进入Laf应用开发IDE
在这里插入图片描述
在这里插入图片描述
1.添加NPM依赖
点击左下角【NPM依赖】处的“+”按钮,在弹框中搜索“qiniu”,选中第一个后再点击“保存并重启”,等待3秒左右依赖会添加完成
在这里插入图片描述
2.添加函数
点击左上角【函数列表】处的“+”按钮,在弹框中输入函数名(比如:file-upload),其他默认,完成后点击“确认”按钮,等待3秒左右函数会添加完成
在这里插入图片描述
在这里插入图片描述
说明:关于云函数的入门,可点击 https://doc.laf.run/guide/function/ 链接了解详情
3. 云函数完整代码
1)云函数“file-upload”完整代码如下:

import cloud from '@lafjs/cloud'
import { QiniuStore } from '@/qiniu-store'

const fs = require("fs")

export default async function (ctx: FunctionContext) {
  const _body = ctx.body;
  const _query = ctx.query;
  const _type = _body.type ? _body.type : _query.type;
  //参数校验
  if (!_type) {
    return resultData(-1, '参数type不能为空!');
  }

  const _files = ctx.files;
  switch (_type) {
    case 'uploadFile':
      // 上传文件
      return await uploadFile(_files);
    default:
      return resultData(-1, '请检查参数type是否有误!');
  }
}

// 上传文件
async function uploadFile(files) {
  console.log('uploadFile->files', files);

  const _files = files;
  //参数校验
  if (!_files || _files.length == 0) {
    return resultData(-1, '未上传文件!');
  }
  const fileInfo = _files[0];
  if (!fileInfo.filename) {
    return resultData(-1, '文件名称为空!');
  }
  if (!fileInfo.mimetype) {
    return resultData(-1, '文件类型为空!');
  }
  if (!fileInfo.size || fileInfo.size > 5 * 1024 * 1024) {
    return resultData(-1, '文件大小不能超过5M!');
  }

  try {
    //获取上传文件的对象
    let fileData = await fs.readFileSync(fileInfo.path);
    // 文件存储
    const res = await QiniuStore.uploadFile({ fileName: fileInfo.filename, fileData: fileData });
    return res;
  }
  catch (e) {
    return resultData(-1, '异常错误:' + e.message);
  }
}

//返回结果数据
function resultData(code = -1, msg = '', data = null) {
  return { code, msg, data }
}

说明:前端上传的文件在云函数的ctx.files里可以找到,以下是云函数接收到文件后ctx.files的打印结果范例。

console.log(ctx.files)
// 输出结果
// [
//   {
//     fieldname: 'file',
//     originalname: 'WWcBsfDKw45X965dd934f04a7b0a405467b91800d7ce.jpg',
//     encoding: '7bit',
//     mimetype: 'image/jpeg',
//     destination: '/tmp',
//     filename: 'e6feb0a3-85d7-4fe3-b9ae-78701146acd8.jpg',
//     path: '/tmp/e6feb0a3-85d7-4fe3-b9ae-78701146acd8.jpg',
//     size: 219043
//   }
// ]

2)云函数“qiniu-store”完整代码如下:

import cloud from '@lafjs/cloud'
const moment = require('moment');
// 引入七牛云模块  
const qiniu = require('qiniu');

// 配置七牛云Access Key和Secret Key
const accessKey = 'your access key';
const secretKey = 'your secret key';
// 配置七牛云存储空间名称和域名
const bucket = 'xxx';
const domain = 'http://xxx-xxx.com';

// 七牛云存储
export class QiniuStore {

  /**
   * 上传文件
   * @param {fileData:string,fileName:string} obj
   * @return {object}
  */
  static async uploadFile(obj: any): Promise<object> {
    if (!obj.fileData) {
      return resultData(-1, '文件数据为空!');
    }
    const date = moment();
    let key = 'uploadFiles/' + date.format('YYYYMMDD') + '/';
    if (!obj.fileName) {
      key += Math.ceil(Math.random() * 1000000000000) + '.jpg';
    }
    else {
      key += obj.fileName;
    }

    try {
      // 初始化七牛云SDK
      const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
      const config = new qiniu.conf.Config();
      // 空间对应的机房
      config.zone = qiniu.zone.Zone_z2;
      const formUploader = new qiniu.form_up.FormUploader(config);
      const putExtra = new qiniu.form_up.PutExtra();

      // 生成上传凭证
      const options = {
        scope: bucket + ':' + key,
      };
      const putPolicy = new qiniu.rs.PutPolicy(options);
      const uploadToken = putPolicy.uploadToken(mac);
      const res = await new Promise((resolve, reject) => {
        // 上传文件,fileData-文件完整路径、字节数组和数据流三种方式都支持
        formUploader.put(uploadToken, key, obj.fileData, putExtra, function (respErr,
          respBody, respInfo) {
          if (respErr) {
            console.log('respErr', respErr);
            reject(null);
          }
          if (respInfo.statusCode == 200) {
            console.log('respBody', respBody);
            // 返回文件url
            resolve(domain + '/' + key);
          } else {
            console.log('respInfo', respInfo);
            console.log('respBody', respBody);
            reject(null);
          }
        });
      });
      // 直接返回文件url
      // return resultData(0, 'success', res);

      // 获取文件信息
      return await this.getFileInfo(key);
    }
    catch (e) {
      console.log('七牛云上传异常', e.message);
      return resultData(-1, '上传异常:' + e.message);
    }
  }

  /**
   * 获取文件信息
   * @param {key} key
   * @return {object}
  */
  static async getFileInfo(key: string): Promise<object> {
    if (!key) {
      return resultData(-1, '文件key不能为空');
    }

    try {
      // 初始化七牛云SDK
      const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
      const config = new qiniu.conf.Config();
      // 空间对应的机房
      config.zone = qiniu.zone.Zone_z2;
      // 构建BucketManager对象
      const bucketManager = new qiniu.rs.BucketManager(mac, config);

      const res = await new Promise((resolve, reject) => {
        // 获取文件信息
        bucketManager.stat(bucket, key, function (err, respBody, respInfo) {
          if (err) {
            console.log('err', err);
            reject(null);
          } else {
            if (respInfo.statusCode == 200) {
              console.log('respBody', respBody);
              // 返回文件信息
              let lastIndex = key.lastIndexOf('/');
              resolve({
                fileName: key.substr(lastIndex + 1),
                fileUrl: domain + '/' + key,
                fileType: respBody.mimeType,
                fileSize: respBody.fsize
              });
            } else {
              console.log('respInfo', respInfo);
              console.log('respBody', respBody);
              reject(null);
            }
          }
        });
      });
      return resultData(0, 'success', res);
    }
    catch (e) {
      console.log('七牛云获取文件信息异常', e.message);
      return resultData(-1, '获取文件信息异常:' + e.message);
    }
  }
}

//返回结果数据
function resultData(code = -1, msg = '', data = null) {
  return { code, msg, data }
}

其中关于Zone对象和机房的关系如下:
机房 Zone对象
华东 qiniu.zone.Zone_z0
华北 qiniu.zone.Zone_z1
华南 qiniu.zone.Zone_z2
北美 qiniu.zone.Zone_na0

完成后将两个云函数进行发布。

四、最终效果

使用Apipost调用文件上传(file-upload)接口如下:
在这里插入图片描述
然后返回到七牛云控制台,进入【对象存储】-【空间管理】下的“文件管理”,查看刚刚上传过的文件,如下图:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值