首页 > 解决方案 > 无法在 ubuntu 18.04 中使用 apache commons vfs for vsftpd 重命名文件

问题描述

我正在尝试使用 apache commons vfs 重命名 vsftpd 服务器中的文件,moveTo 函数在本地系统操作系统(Kubuntu 19.04)和 VSFTPD 服务器中运行良好,但是当我尝试在具有 ubuntu 18.04 的测试环境中重命名文件时我不是能够重命名我遇到异常的文件。

使用此代码:

    public static boolean move(String hostName, String username, String password, String remoteSrcFilePath,
        String remoteDestFilePath, byte [] data) {

    FileObject remoteFile = null;
    FileObject remoteDestFile = null;
    boolean result = false;

    try (StandardFileSystemManager manager = new StandardFileSystemManager()){
        manager.init();

        // Create remote object
        remoteFile = manager.resolveFile(
                createConnectionString(hostName, username, password, remoteSrcFilePath), createDefaultOptions());
        remoteDestFile = manager.resolveFile(
                createConnectionString(hostName, username, password, remoteDestFilePath), createDefaultOptions());

        if (!remoteDestFile.exists() && remoteFile.exists()) {
            remoteFile.moveTo(remoteDestFile);
            if(null != data)
                writeData(remoteDestFile, data);
            result =  true;
        }else {
            throw new DataIntegrityViolationException("Destination path already exists");
        }
    } catch (IOException e) {
        logger.error("Error while renaming/moving file",e);
    }  finally {
        try {
            if(null != remoteDestFile)
                remoteDestFile.close();

            if(null != remoteFile)
                remoteFile.close();

        } catch (FileSystemException e) {
            logger.warn("error while closing fileobject "+e.getMessage());
        }
    }
    return result;
}

    public static FileSystemOptions createDefaultOptions() throws FileSystemException {
    // Create SFTP options
    FileSystemOptions opts = new FileSystemOptions();

    // SSH Key checking
    SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");

    /*
     * Using the following line will cause VFS to choose File System's Root as VFS's
     * root. If I wanted to use User's home as VFS's root then set 2nd method
     * parameter to "true"
     */
    // Root directory set to user home
    SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);

    // Timeout is count by Milliseconds
    SftpFileSystemConfigBuilder.getInstance().setConnectTimeoutMillis(opts, 10000);

    return opts;
    }
}

我有这个例外

org.apache.commons.vfs2.FileSystemException: Could not determine if file "sftp://ftpuser:***@ip_address/home/ftpuser/ftp/1/Documents/test1/test2" is writeable

请注意,上面的代码在本地运行良好。

标签: javasftpubuntu-18.04apache-commons-vfsvsftpd

解决方案


如果您遵循apache commons vfs for moveTo()的源代码,您会发现:

if (canRenameTo(destFile)) {            //src and dest have the same FS
  if (!getParent().isWriteable()) {     // <-- it could throw the same exception here
    throw new FileSystemException("vfs.provider/rename-parent-read-only.error", getName(),
                    getParent().getName());
  }
} else {
  if (!isWriteable()) {    // <---- it throws inside here (IMO) rather than returning false 
    throw new FileSystemException("vfs.provider/rename-read-only.error", getName());
  }
}

...,您会发现 moveTo(),如果目标文件不可写但以一种灾难性的方式(例如在isWriteable(file)其主体内引发异常而不是返回),则会抛出您看到的异常false

我的第一个电话是验证sftpd 进程ftp 用户是否可以写入您希望将文件移动到的目录。


推荐阅读