avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 前端读取文件夹并通过 SSH 上传
文章

前端读取文件夹并通过 SSH 上传

发表于 2025-10-7 更新于 2025-10- 7
作者 mdo
9~12 分钟 阅读

在 Web 应用中,除了单文件上传,很多时候我们还需要用户直接选择整个文件夹,并批量上传到远程服务器。典型场景包括:静态资源部署、文档归档、远程备份等。本文整合了 前端文件夹选择方案(webkitdirectory + File System Access API) 与 Node.js + node-ssh 后端上传,实现端到端的完整流程。


前端部分:选择文件夹并上传

前端的目标是让用户选择目录,遍历其中所有文件,并逐一上传到后端。

方案一:webkitdirectory

这是目前兼容度最好的方式,Chrome、Edge、Safari 均支持。

<input type="file" id="folder" webkitdirectory multiple>
<script>
  document.getElementById('folder').addEventListener('change', async (event) => {
    const files = event.target.files;

    for (const file of files) {
      console.log(file.webkitRelativePath, file.name);

      const formData = new FormData();
      formData.append("file", file, file.webkitRelativePath);

      await fetch("http://localhost:3000/upload", {
        method: "POST",
        body: formData
      });
    }
  });
</script>

优点

  • ✅ 兼容度较好,支持主流浏览器。
  • ✅ 能保留相对路径,方便后端还原目录结构。

缺点

  • ❌ Firefox 支持度差。
  • ❌ 必须通过 <input> 触发,不够灵活。

方案二:File System Access API

这是现代浏览器支持的新特性,可以通过 JS 调用目录选择器。

<script>
async function readDir() {
  const dirHandle = await window.showDirectoryPicker();

  for await (const entry of dirHandle.values()) {
    if (entry.kind === "file") {
      const file = await entry.getFile();
      console.log(entry.name);

      const formData = new FormData();
      formData.append("file", file, entry.name);

      await fetch("http://localhost:3000/upload", {
        method: "POST",
        body: formData
      });
    }
  }
}
</script>

<button onclick="readDir()">选择文件夹并上传</button>

优点

  • ✅ 灵活,可结合按钮、拖拽交互。
  • ✅ 支持读写权限,可操作文件。

缺点

  • ❌ 兼容性差,仅 Chromium 内核浏览器支持(Chrome、Edge)。
  • ❌ 需要用户手动授权目录访问。

Node.js 后端:接收并通过 SSH 上传

后端主要任务:接收前端传输的文件 → 缓存到本地 → 通过 SSH 上传到远程服务器 → 删除缓存。

安装依赖

npm install express multer node-ssh

完整后端代码

const express = require('express')
const multer = require('multer')
const { NodeSSH } = require('node-ssh')
const path = require('path')
const fs = require('fs')

const app = express()
const upload = multer({ dest: 'uploads/' })
const ssh = new NodeSSH()

// SSH 配置
const sshConfig = {
  host: 'your-server-ip',
  username: 'your-username',
  privateKey: '/path/to/private/key' // 或 password
}

// 接收文件上传
app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    const localPath = req.file.path
    const remotePath = path.join('/remote/dir', req.file.originalname)

    await ssh.connect(sshConfig)
    await ssh.putFile(localPath, remotePath)

    fs.unlinkSync(localPath)

    res.send('上传成功')
  } catch (err) {
    console.error(err)
    res.status(500).send('上传失败')
  }
})

app.listen(3000, () => {
  console.log('服务已启动: http://localhost:3000')
})

工作流程

  1. 前端选择目录,逐个文件打包成 FormData。
  2. 文件 POST 到后端 /upload。
  3. 后端存储临时文件,再通过 node-ssh 传输到远程服务器。
  4. 删除临时文件,完成上传。

优缺点对比

前端

  • webkitdirectory:兼容更好,但交互有限。
  • File System Access API:交互灵活,但兼容性差。

后端

  • 采用 express + multer,简单易用。
  • 借助 node-ssh,实现自动化远程部署。

总结

  • 如果项目需要支持更多浏览器,推荐 webkitdirectory。
  • 如果项目环境可控,推荐 File System Access API,更灵活。
  • 后端使用 Node.js + node-ssh,能快速实现从前端到服务器的自动化传输。

该方案特别适合 批量文件上传、静态资源部署、远程备份 等场景。

知识库
前端
许可协议:  CC BY 4.0
分享

相关文章

10月 7, 2026

比尔盖茨的智慧:想多赚钱,就每天循环做这3件事

我们总有一种非常固执的错觉,认为那些站在财富金字塔顶端的人,必然拥有某种超越常人的特异功能。我们在脑海中给比尔盖茨这样的大佬描绘了一幅极其悲壮的奋斗画像。大家总觉得,他之所以能富可敌国,肯定是因为他每天只睡三个小时,同时对着八个电脑屏幕疯狂敲击键盘,每一秒钟都在做出价值几亿美金的生死抉择。 为了模仿

9月 28, 2026

程序员越想创业,越不要急着动手

一个能源方面的前辈找到我,希望通过我把一些人工的工作 AI 自动化。 能源方面我不懂,找 Gemini 聊完发现这个是可以复制的,非常兴奋。我跟老婆说,这个项目做好以后可以做成平台,推广到其他公司,你就等着做总裁夫人吧! 她听完以后跟我说,这个项目还是太定制化,和我之前做的一个项目很像。 那个项目一

9月 25, 2026

忍了一年多,我终于对i18n下手了过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道

前言 大家好,我是奈德丽。 过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道。熟悉我的朋友都知道,我这个人比较“惜力”(并不是,实际上只是忍不下去了),对于重复笨拙的工作非常抵触,于是,我开始思考如何优化团队的多语言管理模式。 痛点背景 先说说我们在机票项目中遇到的

下一篇

通用管理后台likeadmin

上一篇

LTO 汽车登记续期简易指南

最近更新

  • 比尔盖茨的智慧:想多赚钱,就每天循环做这3件事
  • iOS 侧载(Sideloading)工具
  • 程序员越想创业,越不要急着动手
  • 注册 Chat Participant
  • 中秋给在外游子的一封信

热门标签

API CodeGeex Coding Cursor DeepSeek Docker Gitkraken Harness Laravel Management

目录

©2026 mdo. 保留部分权利。