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

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 BytesIOclient = 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 带 \r\n,Linux 服务端可能因 XML 声明中的 encoding="UTF-8" 误判为非法字符。
- 用
file -i /tmp/data.xml和sftp.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/pathURL 中密码明文写死,审计不通过;而 JSch/paramiko 可自然对接密钥管理器(如 HashiCorp Vault SDK)
实际上传 XML 最容易卡在“没报错但对方收不到”——八成是路径权限不对(SFTP 用户 home 目录外不可写)、SELinux 上下文限制(ls -Z 查看)、或 XML 文件本身开头有不可见控制字符(用 hexdump -C data.xml | head 检查前 16 字节)。先确认文件能本地解析成功,再上传,别跳步。









