SFTP上传XML文件 Java/Python如何通过SFTP库传输

11次阅读

jsch上传xml需三步:连接、认证(设StrictHostKeyChecking)、传输(用InputStream避免编码问题);paramiko需处理bom和异常;注意换行符、权限及隐藏字符。

SFTP上传XML文件 Java/Python如何通过SFTP库传输

java用JSch上传XML文件:连接、认证、传输三步到位

JSch 是 Java 最常用的 SFTP 客户端库,轻量且稳定,但默认不校验 host key,容易忽略安全风险。

  • 必须显式调用 setConfig("StrictHostKeyChecking", "no") 或提供 KnownHosts 文件,否则首次连接会抛 JSchException: UnknownHostKey
  • XML 文件建议用 put(InputStream, String) 重载,避免本地路径编码问题(尤其含中文时)
  • 不要用 channelSftp.put(String) 直传路径字符串——它会尝试读取本地文件,但不报错失败时静默跳过
session session = new JSch().getSession("user", "host", 22); session.setPassword("pass"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); ChannelSftp sftp = (ChannelSftp) session.openChannel("sftp"); sftp.connect(); 

// 正确:用 InputStream 显式控制内容 sftp.put(new FileInputStream("/tmp/data.xml"), "/remote/data.xml");

sftp.disconnect(); session.disconnect();

python用paramiko上传XML:注意编码与异常捕获

paramiko 的 SFTPClient.put() 表面简单,但 XML 文件若含 BOM 或非 UTF-8 编码,上传后服务端解析常报 XMLSyntaxError: not well-formed

  • 上传前用 open(... , encoding="utf-8-sig") 读取并写入临时 BytesIO,可自动剥离 BOM
  • put() 不抛网络异常(如断连),需配合 try/except (IOError, OSError) 捕获底层错误
  • 避免直接传 localpath="/tmp/data.xml"——如果该路径被其他进程锁住或权限不足,paramiko 默认静默失败,日志里只显示 SSHException: Channel closed.
import paramiko from io import BytesIO 

client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect("host", username="user", password="pass") sftp = client.open_sftp()

with open("/tmp/data.xml", "rb") as f: content = f.read() # 保持原始字节流,不 decode sftp.putfo(BytesIO(content), "/remote/data.xml")

sftp.close() client.close()

XML上传后解析失败?检查换行符与服务器端编码

SFTP 本身不转换文本内容,但部分 SFTP 服务端(如某些 OpenSSH 配置)或目标应用(如 Java Web Service)对行尾符敏感。windows 生成的 XML 带 rnlinux 服务端可能因 XML 声明中的 encoding="UTF-8" 误判为非法字符。

  • file -i /tmp/data.xmlsftp.get() 下载已上传文件比对,确认换行符是否被修改(正常情况不应变)
  • 如果服务端用 Java DocumentBuilder 解析失败,加一行 System.setProperty("file.encoding", "UTF-8"); 再试
  • OpenSSH 的 sftp-server 默认不处理换行,但某些定制 SFTP 服务(如 Tectia)启用了文本模式,此时应禁用:sftp.put(..., preserve_mtime=False) 并确认未启用 convert 参数

要不要用 apache Commons VFS?谨慎评估

VFS 抽象了 SFTP/FTP/WebDAV 等协议,但对 XML 场景反而增加不确定性:它的 FileObject.getContent().getInputStream() 在 SFTP 场景下会缓存整个文件到内存,大 XML(>50MB)易触发 OOM;且其 FileSystemManager 初始化慢,连接池配置晦涩。

立即学习Java免费学习笔记(深入)”;

  • 仅当项目已重度依赖 VFS 且上传逻辑分散在多协议中,才考虑统一接入
  • 否则优先用 JSch / paramiko 原生 API,可控性高,出错时指向明确(比如 java.net.SocketTimeoutException 直接暴露是网络层问题)
  • VFS 的 sftp://user:pass@host/path URL 中密码明文写死,审计不通过;而 JSch/paramiko 可自然对接密钥管理器(如 HashiCorp Vault SDK)

实际上传 XML 最容易卡在“没报错但对方收不到”——八成是路径权限不对(SFTP 用户 home 目录外不可写)、SELinux 上下文限制(ls -Z 查看)、或 XML 文件本身开头有不可见控制字符(用 hexdump -C data.xml | head 检查前 16 字节)。先确认文件能本地解析成功,再上传,别跳步。

text=ZqhQzanResources