Node.js+Express.js+TS实现简单图床脚本

 更新时间:2023年10月16日 10:09:53   作者:泯泷  
在这篇博客文章中,我将介绍如何使用 TypeScript 和 Express 框架来编写一个简单的图床脚本,可以将本地图片上传到服务器,并返回图片的 URL,这样,你就可以在 Markdown 文档中方便地引用图片,而不用担心图片的存储和管理问题

代码实现

我将最新源码放在了MoMeak9/img-service: 简单图床脚本,但是这个是最终版本,添加了很多新的在后续文章才提到的功能,而本文的完整代码我放在了文末,请客官自行取用。

首先,我们需要安装一些依赖包,包括 express、multer 和 dotenv。express 是一个流行的 Node.js Web 框架,提供了基本的路由和中间件功能。multer 是一个用于处理 multipart/form-data 类型的请求体的中间件,可以方便地获取上传的文件。fs 是 Node.js 的内置模块,用于操作文件系统。path 也是 Node.js 的内置模块,用于处理文件路径。dotenv 是一个用于加载环境变量的模块,可以让我们将一些敏感或配置信息存放在 .env 文件中,而不用暴露在代码里。

我们可以使用 npm 或 yarn 来安装这些依赖包:

npm install express multer fs path dotenv
# or
yarn add express multer fs path dotenv

然后,我们需要在项目根目录下创建一个 .env 文件,用来存放一些配置信息,比如服务器端口号、图片存储路径和访问域名等。例如:

PORT=8899
BASEURL=https://fs.lwmc.net

接下来,我们需要在项目根目录下创建一个 src 文件夹,用来存放 TypeScript 源码文件。在 src 文件夹下,我们创建一个 index.ts 文件,作为入口文件。在 index.ts 文件中,我们首先需要导入一些模块:

import express, {NextFunction, Request, Response} from 'express';
import multer from 'multer';
import fs from 'fs';
import path from 'path';
import dotenv from 'dotenv';

你也看出来了,我们还需要添加一些类型辅助

npm install @types/express @types/multer @types/node -D
# or
yarn add @types/express @types/multer @types/node -D

跨域配置(上传和静态文件跨域访问能力)

// 允许跨域请求
app.use((req: Request, res: Response, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    next();
});

路由

应该包含有静态资源路由和上传路由:

静态资源路由开放对/uploads路径下资源的访问

// 静态文件路由
app.use('/uploads', express.static(path.resolve(__dirname, '../uploads')));

上传路由开放对/uploadPOST方法的访问:

  • upload.single('file') 是一个 multer 中间件,表示只允许上传一个文件,并且上传的文件参数名是 'file'。
  • (req: Request, res: Response) => { ... } 是路由处理函数,当客户端向 '/upload' 路径发送 POST 请求时,会执行这个函数。
  • const file = req.file; 表示从请求中获取上传的文件。
  • if (!file) { ... } 表示如果没有上传文件,返回一个 400 错误响应。
  • res.send({ ... }) 表示向客户端发送一个 JSON 响应,包含上传文件的信息,包括文件名、原始文件名、文件类型、文件大小和文件的访问路径。其中文件访问路径是通过拼接服务器地址和文件路径得到的。
// 上传文件路由
app.post('/upload', upload.single('file'), (req: Request, res: Response) => {
    const file = req.file;
    if (!file) {
        res.status(400).send('Please upload a file.');
        return;
    }
    
    // 返回文件信息
    res.send({
        filename: file.filename,
        originalname: file.originalname,
        mimetype: file.mimetype,
        size: file.size,
        path: `http://localhost:3000/${commonPath}/${file.filename}`,
    });
    // 复原公共路径
    commonPath = 'uploads/'
});

multer 配置

代码使用了 multer 中间件来处理上传文件的请求。Multer 是一个 node.js 中间件,用于处理文件上传,支持多文件上传,可以设置文件大小、文件类型和保存路径等。

以下是对代码配置项的解释:

  • dest 属性指定上传文件的保存目录,这里设置为 'uploads/' 目录下。如果目录不存在,则会自动创建。
  • limits 属性设置上传文件的限制,这里限制文件大小为 10MB。
  • fileFilter 属性指定上传文件的类型,这里限制只能上传 image/png、image/jpeg、image/gif、image/webp、image/svg+xml 这些类型的文件。如果文件类型不在指定的类型列表中,则会触发错误。
  • storage 属性指定上传文件的存储方式,这里使用了 diskStorage 存储方式。在存储文件时,会根据上传时间按年月日来创建文件夹,并将文件存储在对应的文件夹下。
  • filename 方法指定上传文件的命名规则,这里使用时间戳加原始文件名的方式来命名文件。
// 上传文件的中间件
const upload = multer({
    dest: 'uploads/',
    limits: {
        fileSize: 1024 * 1024 * 10, // 限制文件大小为10M
    },
    fileFilter: (req, file, cb) => {
        // 限制文件类型
        const allowedTypes = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'];
        if (!allowedTypes.includes(file.mimetype)) {
            cb(new Error('Invalid file type.'));
            return;
        }
        cb(null, true);
    },
    storage: multer.diskStorage({
        destination: (req, file, cb) => {
            if (!fs.existsSync('uploads/')) {
                fs.mkdirSync('uploads/');
            }
            // 获取日期
            const date = new Date();
            const year = date.getFullYear();
            const month = date.getMonth() + 1;
            const day = date.getDate();
            commonPath = path.join(commonPath, year.toString());
            if (!fs.existsSync(path.join(commonPath))) {
                fs.mkdirSync(path.join(commonPath));
            }
            commonPath = path.join(commonPath, month.toString().padStart(2, '0'));
            if (!fs.existsSync(path.join(commonPath))) {
                fs.mkdirSync(path.join(commonPath));
            }
            // 拼接路径
            cb(null, commonPath);
        },
        filename: (req, file, cb) => {
            cb(null, `${Date.now()}${file.originalname}`);
        },
    }),
});

完整代码:

import express, {Request, Response} from 'express';
import multer from 'multer';
import fs from 'fs';
import path from 'path';
const app = express();
// 公共路径
let commonPath = 'uploads/';
// 上传文件的中间件
const upload = multer({
    dest: 'uploads/',
    limits: {
        fileSize: 1024 * 1024 * 10, // 限制文件大小为10M
    },
    fileFilter: (req, file, cb) => {
        // 限制文件类型
        const allowedTypes = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'];
        if (!allowedTypes.includes(file.mimetype)) {
            cb(new Error('Invalid file type.'));
            return;
        }
        cb(null, true);
    },
    storage: multer.diskStorage({
        destination: (req, file, cb) => {
            if (!fs.existsSync('uploads/')) {
                fs.mkdirSync('uploads/');
            }
            // 获取日期
            const date = new Date();
            const year = date.getFullYear();
            const month = date.getMonth() + 1;
            const day = date.getDate();
            commonPath = path.join(commonPath, year.toString());
            if (!fs.existsSync(path.join(commonPath))) {
                fs.mkdirSync(path.join(commonPath));
            }
            commonPath = path.join(commonPath, month.toString().padStart(2, '0'));
            if (!fs.existsSync(path.join(commonPath))) {
                fs.mkdirSync(path.join(commonPath));
            }
            // 拼接路径
            cb(null, commonPath);
        },
        filename: (req, file, cb) => {
            cb(null, `${Date.now()}${file.originalname}`);
        },
    }),
});
// 允许跨域请求
app.use((req: Request, res: Response, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    next();
});
// 静态文件路由
app.use('/uploads', express.static(path.resolve(__dirname, '../uploads')));
// 上传文件路由
app.post('/upload', upload.single('file'), (req: Request, res: Response) => {
    const file = req.file;
    if (!file) {
        res.status(400).send('Please upload a file.');
        return;
    }
    // 返回文件信息
    res.send({
        filename: file.filename,
        originalname: file.originalname,
        mimetype: file.mimetype,
        size: file.size,
        path: `http://localhost:3000/${commonPath}/${file.filename}`,
    });
    commonPath = 'uploads/'
});
// 启动服务器
const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`server started at http://localhost:${port}`);
});

以上就是Node.js+Express.js+TS实现简单图床脚本的详细内容,更多关于Node.js Express.js TS图床脚本的资料请关注脚本之家其它相关文章!

相关文章

  • Node.js实现mysql连接池使用事务自动回收连接的方法示例

    Node.js实现mysql连接池使用事务自动回收连接的方法示例

    这篇文章主要介绍了Node.js实现mysql连接池使用事务自动回收连接的方法,结合实例形式分析了node.js操作mysql连接池实现基于事务的连接回收操作相关技巧,需要的朋友可以参考下
    2018-02-02
  • 解决Node.js包管理器安装报错npm ERR! code 1的问题

    解决Node.js包管理器安装报错npm ERR! code 1的问题

    在开发过程中,我们经常需要使用各种Node.js包来扩展我们的应用程序功能,这些包通常通过npm(Node.js包管理器)进行安装和管理,有时候我们可能会遇到一些关于npm的错误,本文将详细介绍如何解决这个问题,并提供一个详细的实例,需要的朋友可以参考下
    2024-03-03
  • Node.js文件操作详解

    Node.js文件操作详解

    这篇文章主要介绍了Node.js文件操作详解,本文讲解了处理文件路径讲的一些方法、fs模块详细的使用和介绍等内容,需要的朋友可以参考下
    2014-08-08
  • nodejs接入阿里大鱼短信验证码的方法

    nodejs接入阿里大鱼短信验证码的方法

    本篇文章主要介绍了nodejs接入阿里大鱼短信验证码的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-07-07
  • 利用node实现数据库数据导出到Excel

    利用node实现数据库数据导出到Excel

    本文将详细讲解如何使用Node.js实现从MySQL数据库获取数据,并生成包含多个工作表的 Excel 文件,每个工作表对应数据库中的一个表,有需要的可以了解下
    2024-11-11
  • node.js中的fs.fchown方法使用说明

    node.js中的fs.fchown方法使用说明

    这篇文章主要介绍了node.js中的fs.fchown方法使用说明,本文介绍了fs.fchown方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下
    2014-12-12
  • npm does not support Node.js问题的解决办法

    npm does not support Node.js问题的解决办法

    这篇文章主要给大家介绍了关于npm does not support Node.js问题的解决办法,文中通过代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10
  • node.js实现websocket的即时通讯详解

    node.js实现websocket的即时通讯详解

    这篇文章主要介绍了深入浅出讲解websocket的即时通讯,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种,需要的朋友可以参考下
    2023-05-05
  • nodejs+websocket实时聊天系统改进版

    nodejs+websocket实时聊天系统改进版

    这篇文章主要介绍了nodejs+websocket实时聊天系统的改进版,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • VsCode开发环境之Node.js离线部署的实现步骤

    VsCode开发环境之Node.js离线部署的实现步骤

    本文主要介绍了VsCode开发环境之Node.js离线部署的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09

最新评论