You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将HDFS中的Zip文件复制到SFTP服务器?遇目录报错求解决

问题分析与解决方案

核心问题

你HDFS路径下的FileName.zip不是真实的Zip文件,而是一个Hadoop任务输出的目录(从_SUCCESS、part-0000000.txt这类文件就能判断,这是MapReduce/Spark任务输出的典型目录结构)。当你试图把它当作普通文件用InputStream读取时,就会触发"Is a directory"的错误。


解决方案

1. 先确认HDFS路径的真实类型

执行HDFS命令验证:

hdfs dfs -ls /path/to/FileName.zip

如果输出开头是drwxr-xr-x,说明这确实是目录而非文件。

2. 方案一:把HDFS目录打包成真实Zip后上传(推荐)

如果需要上传的是完整的Zip文件,有两种实现方式:

  • 集群端命令打包
    先把HDFS目录拉到本地节点,再打包成Zip,最后上传到SFTP:
    # 拉取HDFS目录到本地临时路径
    hdfs dfs -get /path/to/FileName.zip /local/temp/
    # 进入目录并打包
    cd /local/temp/FileName.zip
    zip -r /local/temp/RealFileName.zip .
    # 直接从本地传到SFTP(用sftp命令)
    sftp user@sftp-server <<EOF
    put /local/temp/RealFileName.zip /sftp/dest/path/
    EOF
    
  • Java代码内打包成Zip流上传
    直接在代码里遍历HDFS目录文件,生成Zip流后传给ChannelSftp:
    Configuration conf = new Configuration();
    FileSystem fs = FileSystem.get(conf);
    Path hdfsDirPath = new Path("/path/to/FileName.zip");
    
    // 构建Zip输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ZipOutputStream zipOut = new ZipOutputStream(baos);
    
    // 遍历HDFS目录下的文件
    RemoteIterator<LocatedFileStatus> fileIterator = fs.listFiles(hdfsDirPath, false);
    while (fileIterator.hasNext()) {
        LocatedFileStatus fileStatus = fileIterator.next();
        Path filePath = fileStatus.getPath();
        String fileName = filePath.getName();
        
        // 可选:跳过_SUCCESS文件
        if (fileName.equals("_SUCCESS")) continue;
    
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
    
        // 读取HDFS文件内容写入Zip流
        InputStream in = fs.open(filePath);
        IOUtils.copy(in, zipOut);
        in.close();
        zipOut.closeEntry();
    }
    zipOut.close();
    
    // 上传Zip流到SFTP
    ChannelSftp sftp = ...; // 已初始化的ChannelSftp实例
    sftp.put(new ByteArrayInputStream(baos.toByteArray()), "/sftp/dest/RealFileName.zip");
    

3. 方案二:直接上传目录内的所有文件到SFTP

如果不需要打包成Zip,可直接把目录里的文件逐个传到SFTP对应目录:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path hdfsDirPath = new Path("/path/to/FileName.zip");
String sftpDestDir = "/sftp/dest/FileName/";

// 创建SFTP目标目录
sftp.mkdir(sftpDestDir);

// 遍历并上传文件
RemoteIterator<LocatedFileStatus> fileIterator = fs.listFiles(hdfsDirPath, false);
while (fileIterator.hasNext()) {
    LocatedFileStatus fileStatus = fileIterator.next();
    Path filePath = fileStatus.getPath();
    String fileName = filePath.getName();
    
    // 可选:跳过_SUCCESS文件
    if (fileName.equals("_SUCCESS")) continue;

    InputStream in = fs.open(filePath);
    sftp.put(in, sftpDestDir + fileName);
    in.close();
}

错误原因复盘

你调用put(InputStream, destPath)时,传入的InputStream是尝试从HDFS的FileName.zip目录打开的,但HDFS的目录无法直接用fs.open()打开为流,因此抛出了"FileNotFoundException: Is a directory"——本质是误将目录当作普通文件处理。

内容的提问来源于stack exchange,提问作者Glarixon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:17:12