从SFTP传输文件至ADLS:Databricks Scala环境下sshj库的abfss路径传递方法咨询
使用sshj将SFTP文件下载至ADLS Gen2(Databricks Scala环境)
我来帮你梳理下这个问题的解决方案,毕竟在Databricks里用sshj对接ADLS确实有几个需要注意的点:
一、为什么直接传abfss路径给FileSystemFile行不通
首先得明确:sshj的FileSystemFile是基于本地文件系统实现的,它底层依赖java.io.File,而这个类根本不认识abfss这种云存储协议。所以你直接把abfss路径传进去,肯定会报路径解析错误——它只会把这个路径当成本地文件系统里的路径来找,自然找不到对应的位置。
二、正确的实现方式:通过数据流中转
在Databricks Scala环境里,我们可以用输入流+ADLS文件系统API的方式来实现,步骤如下:
- 从SFTP服务器获取文件的输入流
- 利用Databricks已配置好的ADLS连接,把输入流写入目标abfss路径
具体代码示例:
import net.schmizz.sshj.SSHClient import net.schmizz.sshj.sftp.SFTPClient import org.apache.hadoop.fs.{FileSystem, Path} import java.io.InputStream import org.apache.commons.io.IOUtils // 初始化SSH/SFTP客户端(替换成你的SFTP服务器信息和认证方式) val sshClient = new SSHClient() sshClient.connect("your-sftp-host.com") sshClient.authPassword("sftp-username", "sftp-password") // 或者用密钥认证 val sftpClient = sshClient.newSFTPClient() try { // 1. 获取SFTP文件的输入流 val sftpInputStream = sftpClient.getRemoteFileStream("test_file") // 2. 获取ADLS文件系统实例(Databricks自动读取集群配置的ADLS权限) val adlsFs = FileSystem.get(spark.sparkContext.hadoopConfiguration) // 3. 构建目标abfss路径:必须包含完整文件名! val targetAbfssPath = new Path( "abfss://<container_name>@<storage_account>.dfs.core.windows.net/<folder-path>/test_file" ) // 4. 将输入流写入ADLS val outputStream = adlsFs.create(targetAbfssPath) try { IOUtils.copy(sftpInputStream, outputStream) // 用IOUtils简化流拷贝 } finally { // 务必关闭流资源 outputStream.close() sftpInputStream.close() } } finally { // 关闭SFTP和SSH客户端 sftpClient.close() sshClient.disconnect() }
三、关于目标路径的疑问:必须包含文件名
答案很明确:必须指定完整的文件路径(文件夹+文件名)。原因是:
- ADLS的
create方法需要明确知道要创建的文件名称,只传文件夹路径的话,它无法确定要生成的文件叫什么,会直接报错。 - 如果你想保持和SFTP上一样的文件名,直接把原文件名拼在abfss的文件夹路径后面就行;如果要重命名,就换成你想要的文件名。
补充提示
- 确保你的Databricks集群已经正确配置了ADLS Gen2的访问权限(比如服务主体、SAS Token或托管身份),这样
FileSystem.get才能正常获取到ADLS的文件系统实例。 - 示例中用到的
IOUtils来自Apache Commons IO,Databricks默认环境已经包含这个依赖,不用额外引入。 - 如果你需要处理大文件,流拷贝的方式也很高效,不会把整个文件加载到内存里,适合Databricks的集群环境。
内容的提问来源于stack exchange,提问作者rainingdistros
相关产品推荐
相关产品推荐

