基于 Koa2 实现一个简单的上传服务和下载服务

Koa2 是一个基于 Node.js 的轻量级框架,它提供了一套简单、强大的 API,让开发者能够轻松构建 Web 应用程序。在 Web 应用程序的开发中,通常需要实现上传和下载的功能,本文将介绍如何基于 Koa2 实现一个简单的上传服务和下载服务。

准备工作

在开始编写代码前,我们需要安装几个依赖包:

  • Koa2
  • Koa-body
  • Koa-router
  • Multer
  • Mime-types

我们可以使用 npm 进行安装:

npm install koa koa-body koa-router multer mime-types --save

实现上传服务

初始化 Koa2 应用程序

我们可以通过以下代码初始化一个 Koa2 应用程序:

const Koa = require('koa');
const app = new Koa();

配置 Koa-body 和 Multer

Koa-body 是一个中间件,它用于解析 HTTP 请求的 body。Multer 则是一个 Node.js 中间件,用于处理文件上传。我们需要把它们两个都配置到应用程序中:

const KoaBody = require('koa-body');
const Multer = require('multer');

// 配置 Koa-body
app.use(KoaBody());

// 配置 Multer
const storage = Multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/'); // 文件存储的目录
  },
  filename: function (req, file, cb) {
    cb(null, `${file.originalname}`); // 文件名
  }
});
const upload = Multer({ storage: storage });

实现上传接口

下面我们来实现一个上传接口:

const KoaRouter = require('koa-router');
const router = new KoaRouter();

router.post('/upload', upload.single('file'), (ctx, next) => {
  if (ctx.req.file) {
    ctx.status = 200;
    ctx.body = {
      success: true,
      message: '文件上传成功!',
      data: {
        url: `http://localhost:3000/uploads/${ctx.req.file.originalname}`,
      }
    };
  } else {
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: '文件上传失败!',
    };
  }
});

app.use(router.routes());

如上代码所示,我们首先通过 KoaRouter 配置一个上传路由,上传的入口 URL 是 /upload,在上传时使用了 upload.single('file') 中间件,它表示只允许上传一个名为 'file' 的文件。如果上传成功,则返回一个 JSON 响应,包含了成功标志、消息和所上传文件的 URL,否则返回错误消息。

实现下载服务

实现一个下载接口

下面我们来编写一个下载接口,用户可以通过该接口下载上传的文件:

const fs = require('fs');
const mime = require('mime-types');

router.get('/download/:filename', async (ctx, next) => {
  const filename = ctx.params.filename;
  const path = `./uploads/${filename}`;
  const fStats = await fs.promises.stat(path);

  if (fStats.isFile()) {
    ctx.set('Content-type', mime.lookup(path));
    ctx.body = fs.createReadStream(path);
  } else if (fStats.isDirectory()) {
    ctx.status = 400;
    ctx.body = {
      success: false,
      message: '无法下载一个目录!',
    };
  }
});

如上代码所示,该接口允许用户通过 /download/:filename 进行下载,:filename 是动态路由参数,表示要下载的文件名称。该接口首先通过 Node.js 的 fs 模块检查文件存在性,并检查用户请求下载的是否是一个目录(目录无法下载)。如果请求下载的是个文件,则设置 Content-type 响应头,并将文件内容通过 fs.createReadStream 输出到响应主体中。

总结

到此为止,我们已经介绍了基于 Koa2 实现一个简单的上传和下载服务的实现过程,其中使用了 Koa-body、Koa-router、Multer 和 Mime-types 等多个 Node.js 模块。当然,这个示例还可以进行更加复杂的处理,例如文件格式检查、文件上传进度反馈等等,希望这篇文章能够给读者提供启示,并为日后的项目开发提供帮助。最后,本文的示例代码如下:

const Koa = require('koa');
const app = new Koa();

const KoaBody = require('koa-body');
const Multer = require('multer');
const fs = require('fs');
const mime = require('mime-types');
const KoaRouter = require('koa-router');

app.use(KoaBody());

const storage = Multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/'); // 文件存储的目录
  },
  filename: function (req, file, cb) {
    cb(null, `${file.originalname}`); // 文件名
  }
});
const upload = Multer({ storage: storage });

const router = new KoaRouter();

router.post('/upload', upload.single('file'), (ctx, next) => {
  if (ctx.req.file) {
    ctx.status = 200;
    ctx.body = {
      success: true,
      message: '文件上传成功!',
      data: {
        url: `http://localhost:3000/uploads/${ctx.req.file.originalname}`,
      }
    };
  } else {
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: '文件上传失败!',
    };
  }
});

router.get('/download/:filename', async (ctx, next) => {
  const filename = ctx.params.filename;
  const path = `./uploads/${filename}`;
  const fStats = await fs.promises.stat(path);

  if (fStats.isFile()) {
    ctx.set('Content-type', mime.lookup(path));
    ctx.body = fs.createReadStream(path);
  } else if (fStats.isDirectory()) {
    ctx.status = 400;
    ctx.body = {
      success: false,
      message: '无法下载一个目录!',
    };
  }
});

app.use(router.routes());

app.listen(3000, () => {
  console.log('文件上传下载服务已启动!');
});

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6591094deb4cecbf2d640336


纠错
反馈