边角料技术-ftp 上传文件的坑D经历

264 阅读3分钟

前言

公司小作坊,所以部署前端项目还是通过 mstsc windows 远程连接到服务器手动上传打包后的项目(PS:刚进来公司的我一脸懵逼,还有这样的?),他们甚至都不在服务器上开启FTP的功能,使用 FileZilla Client 这种上传工具。 鉴于每次发布开发环境都需要手动连接服务器copy上传文件,作为一个摸鱼爱好者怎么能容忍此种机械式的重复工作,因此就有了以下一系列的研究。

实践出真知

image.png

  1. 我在服务器(windows server 2012r2)上安装了FTP的相关应用应用并设置了相关上传路径等配置,并使用FileZilla Client 应用程序测试FTP是否正常工作,对此不熟悉的童鞋请自行谷歌百度。
  2. 初步想法每次打包编译完毕后执行node脚本自动上传项目到指定目录,因此通过查阅资料,在下相中了 ftp 使用它我们可以快速链接FTP服务,然后就是使用它的API【mkdirput】上传文件,使用【rmdirdelete】删除文件就完事了,完美撒花(异想天开
  3. 使用 ftp 依赖包确实可以完成非中文文件的上传及删除操作,但是一旦文件名或者文件夹出现中文名称(不出意外的话意外就出现了,哈哈哈哈哈)
const Client = require('ftp')
const { resolve } = require('path')
resolve(__dirname, './test')
const c = new Client()
c.on('ready', function () {
  c.put('呵呵.txt', '呵呵.txt', function (err) {
    if (err) throw err
    c.end()
  })
})
// ftp服务连接地址及端口配置登录配置
c.connect({
  host: '192.168.1.xxx',
  port: '21',
  user: 'xxx',
  password: 'xxx'
})

直接三下五除二写完收工,结果上传到服务器 文件名却变成了:

image.png

image.png

我的 呵呵.txt 呢,什么情况???(稍安勿躁随后就会解决) 上传不行我试试删除:(服务器有呵呵.txt文件)

const Client = require('ftp')
const { resolve } = require('path')
resolve(__dirname, './test')
const c = new Client()
c.on('ready', function () {
   c.delete('呵呵.txt', function (err) {
    if (err) throw err
    c.end()
  })
})
// ftp服务连接地址及端口配置登录配置
c.connect({
  host: '192.168.1.xxx',
  port: '21',
  user: 'xxx',
  password: 'xxx'
})

结果可想而知

image.png 服务器明明存在呵呵.txt文件为何提示我找不到这个文件???你在逗我玩?

真相

其实这是编码问题惹的祸,可能因为依赖包的作者是外国人的原因对中文并不友好(个人推测,哈哈哈哈),因此我们只需要解决乱码问题那么这些问题就迎刃而解了!!!

解决编码问题

const { resolve } = require('path')
const Client = require('ftp')
const { Buffer } = require('buffer')

// 转码
function charset(str, encoding = 'utf8') {
  return Buffer.from(str, encoding).toString('utf8')
}
const c = new Client()
c.on('ready', function () {
// _send 源码方法不在api中,想了解的可以自行查看ftp的源码,其实就是向服务器发送信息
// 灵感来源于 FileZilla Client  应用上传步骤发现他会先推送一个 'OPTS UTF8 ON' 操作
// 查阅资料发现这个操作表示开启utf8编码
  c._send(
    'OPTS UTF8 ON',
    function (err) {
      if (err) throw err
      // 转换服务器上的文件名
      c.put('呵呵.txt', charset('呵呵.txt'), function (err) {
        if (err) throw err
        c.end()
      })
    },
    true
  )
})
// ftp服务连接地址及端口配置登录配置
c.connect({
  host: '192.168.1.xxx',
  port: '21',
  user: 'xxx',
  password: 'xxx'
})

image.png image.png

同理删除也是一样的操作

const { resolve } = require('path')
const Client = require('ftp')
const { Buffer } = require('buffer')

// 转码
function charset(str, encoding = 'utf8') {
  return Buffer.from(str, encoding).toString('utf8')
}
const c = new Client()
c.on('ready', function () {
// _send 源码方法不在api中,想了解的可以自行查看ftp的源码,其实就是向服务器发送信息
// 灵感来源于 FileZilla Client  应用上传步骤发现他会先推送一个 'OPTS UTF8 ON' 操作
// 查阅资料发现这个操作表示开启utf8编码
  c._send(
    'OPTS UTF8 ON',
    function (err) {
      if (err) throw err
      // 因为本地已经是 UTF8的编码了因此不需要转换
      // 如果是通过 list API 查询的服务器目录去删除则需要转 charset(path, 'latin1')
      // 为何是 latin1 请移步nodejs官方文档(Buffer)
       c.delete('呵呵.txt', function (err) {
        if (err) throw err
        c.end()
      })换 
    },
    true
  )
})
// ftp服务连接地址及端口配置登录配置
c.connect({
  host: '192.168.1.xxx',
  port: '21',
  user: 'xxx',
  password: 'xxx'
})

参考资料

nodejs-Buffer

ftp