You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Webpack/Parcel打包basic-ftp模块在浏览器报错求助

问题:basic-ftp在浏览器构建环境中报错,Node环境正常

问题描述

使用Webpack 5或Parcel构建包含basic-ftp@5.0.4的JS文件,在Node.js命令行运行正常,但在Windows 11浏览器中报错,错误指向util.promisify参数类型错误。

浏览器错误信息

Uncaught TypeError: The "original" argument must be of type 
Function
at promisify (util.js:614:11)
at 5u8Fu.c4216f9df743e6cc (Client.js:17:38)
at newRequire (index.47c005a7.js:71:24)
at localRequire (index.47c005a7.js:84:35)
at 2uKas.b1c576accb3ceae3 (index.js:21:14)
at newRequire (index.47c005a7.js:71:24)
at localRequire (index.47c005a7.js:84:35)
at 8Duvb.44a9388bb99fc836 (index1.js:7:16)
at newRequire (index.47c005a7.js:71:24)
at index.47c005a7.js:122:5

相关文件内容

src/index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>My First Parcel App</title>
    <link rel="stylesheet" href="main.css" />
    <script type="module" src="index1.js"></script>
  </head>
  <body>
      <h1>Hello, World!</h1>
  </body>
</html>

src/index1.js

// src/index1.js
// works with node index1.js

console.log("Starting");
const Client = require("basic-ftp")
//import * as Client from "basic-ftp"

example();

async function example() {
const client = new Client.Client()
client.ftp.verbose = true
try {
await client.access({
host: "somehost",
user: "username",
password: "password",
secure: false
})
console.log(await client.list())
//await client.uploadFrom("README.md", "README_FTP.md")
//await client.downloadTo("README_COPY.md", README_FTP.md")
}
catch(err) {
console.log(err) 
}
client.close()
}

console.log("Finished!");

package.json

{
"name": "parcel-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"buffer": "^6.0.3",
"node": "^21.2.0",
"parcel": "^2.10.3"
},
"dependencies": {
"basic-ftp": "^5.0.4"
}
}

依赖列表

+-- basic-ftp@5.0.4
+-- buffer@6.0.3
+-- node-bin-setup@1.1.3 extraneous
+-- node@21.2.0
`-- parcel@2.10.3

构建命令

npx parcel src/index.html --open

解决方案

问题根源在于basic-ftp是Node.js专属库,依赖Node环境特有的API(如net、tls模块,以及util.promisify处理的Node原生异步方法),这些API在浏览器环境中不存在,所以构建后运行会报错。

解决步骤:

  1. 改用后端代理方案:浏览器本身出于安全和协议限制,不支持直接发起FTP连接,需通过Node.js后端完成FTP操作,前端调用后端接口获取结果。
  2. 调整项目架构:将FTP相关逻辑全部移至服务端,前端仅负责发起请求和展示数据。

示例调整(后端代理方式)

1. 新建Node服务文件(server.js)

const express = require('express');
const { Client } = require('basic-ftp');
const app = express();
const port = 3000;

app.use(express.json());

app.get('/ftp/list', async (req, res) => {
  const client = new Client();
  client.ftp.verbose = true;
  try {
    await client.access({
      host: "somehost",
      user: "username",
      password: "password",
      secure: false
    });
    const list = await client.list();
    res.json(list);
  } catch (err) {
    res.status(500).json({ error: err.message });
  } finally {
    client.close();
  }
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

2. 前端修改index1.js

console.log("Starting");

async function example() {
  try {
    const response = await fetch('http://localhost:3000/ftp/list');
    const list = await response.json();
    console.log(list);
  } catch (err) {
    console.log(err);
  }
}

example();
console.log("Finished!");

3. 启动服务并运行前端

  • 安装依赖:npm install express
  • 启动后端:node server.js
  • 启动前端:npx parcel src/index.html --open

通过这种方式,前端通过调用后端接口间接完成FTP操作,避开浏览器环境的限制。


内容的提问来源于stack exchange,提问作者bren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:53:22