npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@electerm/ftp-srv

v1.0.5

Published

Modern, extensible FTP Server (TypeScript version)

Readme

@electerm/ftp-srv

English 中文

现代、可扩展的 FTP 服务器(TypeScript 版本)。

本项目是 ftp-srv 的 TypeScript 重构版本,同时发布 ESM 和 CJS 格式——并修复了原版中的安全漏洞。API 与原版 ftp-srv 向后兼容。

原始实现的全部功劳归于原作者 Tyler Stewart。详见 CREDITS 文件。

安装

npm install @electerm/ftp-srv

使用

// ESM
import FtpServer from '@electerm/ftp-srv';

// CJS
const { FtpServer } = require('@electerm/ftp-srv');

// 向后兼容别名(兼容原始 ftp-srv 包)
const { FtpSrv } = require('@electerm/ftp-srv');

基本示例

import FtpServer from '@electerm/ftp-srv';

const server = new FtpServer({
  url: 'ftp://0.0.0.0:21',
  anonymous: false,
});

server.on('login', ({ connection, username, password }, resolve, reject) => {
  if (username === 'admin' && password === 'secret') {
    return resolve({ root: '/srv/ftp' });
  }
  return reject(new Error('用户名或密码无效'));
});

await server.listen();
console.log('FTP 服务器已在 21 端口启动');

// 优雅关闭
await server.close();

按用户设置根目录

const server = new FtpServer({
  url: 'ftp://0.0.0.0:2121',
  pasv_min: 10000,
  pasv_max: 10100,
  anonymous: false,
});

server.on('login', ({ username, password }, resolve, reject) => {
  if (username === 'alice' && password === 'pass') {
    return resolve({
      root: '/home/alice',
      cwd: '/uploads',  // 初始工作目录(相对于 root)
    });
  }
  return reject(new Error('凭据无效'));
});

await server.listen();

匿名访问

const server = new FtpServer({
  url: 'ftp://0.0.0.0:21',
  anonymous: true,   // 接受任意用户名/密码
  root: '/srv/ftp',  // 所有连接的默认根目录
});

server.on('login', (_, resolve) => resolve({}));

await server.listen();

TLS(FTPS)

import fs from 'fs';

const server = new FtpServer({
  url: 'ftps://0.0.0.0:990',
  tls: {
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.crt'),
  },
});

API

new FtpServer(options)

| 选项 | 类型 | 默认值 | 说明 | |------|------|--------|------| | url | string | 'ftp://127.0.0.1:21' | 监听的协议、主机名和端口。使用 ftp://ftps://。 | | root | string | — | 所有连接的默认根目录(当 login 的 resolve 未指定时使用)。 | | pasv_url | string \| (clientIp: string) => string | 自动检测 | 被动连接时向客户端通告的 IP。省略时,本地连接使用客户端 IP,否则使用服务器绑定地址。 | | pasv_min | number | 1024 | 被动端口范围起始值。 | | pasv_max | number | 65535 | 被动端口范围结束值。 | | anonymous | boolean | false | 允许匿名登录(接受任意用户名/密码)。 | | blacklist | string[] | [] | 全局拒绝的 FTP 命令列表。 | | whitelist | string[] | [] | 全局允许的 FTP 命令列表(其余均拒绝)。 | | greeting | string \| string[] | — | 客户端连接时发送的欢迎消息。 | | tls | object | — | Node.js TLS 选项(keycert 等),用于 ftps:// 连接。 | | file_format | 'ls' \| 'ep' \| function | 'ls' | LIST 响应格式。'ls' = Unix 风格,'ep' = EPLF,或自定义 (stat) => string 函数。 | | log | Logger | bunyan logger | 兼容 bunyan 的日志对象(tracedebuginfowarnerrorfatalchild)。 | | timeout | number | 0 | 空闲 socket 超时时间(毫秒)。0 表示禁用。 | | endOnProcessSignal | boolean | true | 收到 SIGTERM/SIGINT/SIGQUIT 时调用 close() 并退出进程。 |

server.listen()Promise<string>

启动服务器并开始接受连接。

server.close()Promise<void>

优雅关闭所有连接并停止服务器。

事件

login

客户端尝试登录时触发。必须监听此事件并调用 resolvereject

server.on('login', ({ connection, username, password }, resolve, reject) => {
  // 使用每用户选项 resolve:
  resolve({
    root: '/srv/ftp/alice',  // 本次会话的根目录
    cwd: '/',                // 初始工作目录(相对于 root)
    fs: customFsInstance,    // 自定义 FileSystem 实例(可选)
    blacklist: ['DELE'],     // 每连接命令黑名单
    whitelist: [],           // 每连接命令白名单
  });

  // 或拒绝登录:
  reject(new Error('凭据无效'));
});

connect

新客户端 socket 连接时触发(登录前)。

server.on('connect', ({ connection, id, newConnectionCount }) => {});

disconnect

客户端断开连接时触发。

server.on('disconnect', ({ connection, id, newConnectionCount }) => {});

client-error

客户端连接发生错误时触发。

server.on('client-error', ({ connection, context, error }) => {});

server-error

底层 TCP 服务器发生错误时触发。

server.on('server-error', ({ error }) => {});

closing / closed

调用 close() 时及关闭完成后触发。

server.on('closing', () => {});
server.on('closed', () => {});

自定义文件系统

继承 FileSystem 可覆盖服务器读写文件的方式。

import { FileSystem } from '@electerm/ftp-srv';

class MyFileSystem extends FileSystem {
  async list(dirPath = '.') {
    // 返回带有 name 属性的 fs.Stats 类对象数组
    const entries = await super.list(dirPath);
    return entries.filter(e => !e.name.startsWith('.'));  // 隐藏点文件
  }

  async get(fileName) {
    return super.get(fileName);
  }
}

server.on('login', (_, resolve) => {
  resolve({ fs: new MyFileSystem(connection, { root: '/srv/ftp' }) });
});

可覆盖的方法:

| 方法 | 说明 | |------|------| | currentDirectory() | 返回当前工作目录路径。 | | get(fileName) | 返回带有 name 属性的 fs.Stats 类对象。 | | list(dirPath) | 返回带有 name 属性的 fs.Stats 类对象数组。 | | chdir(dirPath) | 切换工作目录,返回新路径。 | | write(fileName, options) | 返回 { stream, clientPath } 用于写入。 | | read(fileName, options) | 返回 { stream, clientPath } 用于读取。 | | delete(fileName) | 删除文件。 | | mkdir(dirPath) | 创建目录。 | | rename(from, to) | 重命名文件或目录。 | | chmod(fileName, mode) | 修改文件权限。 | | getUniqueName(fileName) | 返回唯一文件名(用于 STOU 命令)。 |

导出

import FtpServer, {
  FtpServer,       // 具名导出(同一个类)
  FtpSrv,          // 向后兼容别名,兼容原始 ftp-srv 包
  FileSystem,
  FtpConnection,
  errors,
} from '@electerm/ftp-srv';

命令行

npx electermftpsrv ftp://0.0.0.0:9876 --root ~/Documents

License

MIT