为什么 s3fs 不能像使用 Apache MINA SSHD 的普通文件系统一样工作?

Why doesn't s3fs work like a normal file system with Apache MINA SSHD?

所以我正在尝试创建一个 Java SFTP 服务器作为 Apache S3 存储桶的前端。您通过 SFTP 连接并管理存储桶中的 S3 文件,就像它们是 SFTP 服务器上的文件一样。

我使用 Apache MINA (v1.2.0) 作为 SFTP 服务器,它使用 SftpSubsystemFactory 和默认 FileSystemFactory(提供本地文件系统)工作正常。
我选择了 Amazon-S3-FileSystem-NIO2(v1.3.0) as the FileSystem, which uses the Apache AWS SDK,这似乎是最好的选择

public class S3FileSystemFactory implements FileSystemFactory {
    private URI uri = URI.create("localhost");

    public S3FileSystemFactory(URI uri){
        this.uri = uri;
    }

    public FileSystem createFileSystem(Session session) throws IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        FileSystem s3FileSystem = FileSystems.newFileSystem(uri, new HashMap<String, Object>(), classLoader);
        return s3FileSystem;
    }
}

我只是将其设置为 MINA

FileSystemFactory
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setKeyPairProvider(buildHostKeyProviderFromFile(hostKeyType));
sshd.setPasswordAuthenticator(createPasswordAuthenticator());
sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd.setSubsystemFactories(createSubsystemFactories());
sshd.setFileSystemFactory(createFileSystemFactory());

URI uri = URI.create("s3:///s3.amazonaws.com/my_bucket"); 
FileSystemFactory s3FileSystemFactory = new S3FileSystemFactory(uri);
sshd.setFileSystemFactory(s3FileSystemFactory);

我可以使用 FileZilla/Command 线路连接到此服务器,但它会自动连接到 ImageTransfer 存储桶(而不是 my_bucket)。我可以导航到其他存储桶,甚至是子存储桶,但无法显示内容,一切看起来都像一个空目录。

这可以通过 FileSystem I'm using 来完成,因为我可以列出目录内容,就像这样

    Path p = s3FileSystem.getPath("/my_bucket");
    String contents = "";
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(p, "*")) {
        for (Path file : stream) {
            contents += "\n \t - " + file.getFileName();
        }
    } catch (IOException | DirectoryIteratorException x) {}

我一直在查看 s3fs、MINA 和 AWS 代码(因为文档非常有限),但无法查明此问题的根源。任何人都可以阐明我做错了什么吗?

日志记录

打开所有库的日志记录后,我只能看到一个问题

"HEAD
application/x-www-form-urlencoded; charset=utf-8
Fri, 20 May 2016 09:58:07 GMT
/MYURL/."
2016-05-20 10:58:07.240 DEBUG 13323 --- [system-thread-1] c.a.http.impl.client.SdkHttpClient       : Stale connection check
2016-05-20 10:58:07.243 DEBUG 13323 --- [system-thread-1] c.a.http.impl.client.SdkHttpClient       : Attempt 1 to execute request
2016-05-20 10:58:07.434 DEBUG 13323 --- [system-thread-1] c.a.http.impl.client.SdkHttpClient       : Connection can be kept alive indefinitely
2016-05-20 10:58:07.435 DEBUG 13323 --- [system-thread-1] com.amazonaws.request                    : Received error response: com.amazonaws.services.s3.model.AmazonS3Exception: Not Found (Service: null; Status Code: 404; Error Code: 404 Not Found; Request ID: MYREQID), S3 Extended Request ID: MYEXTREQID

问题是双重的。

首先,Apache MINA SSHDrequires the permission attribute be present for any FileSystem it uses, which is strange as that's a POSIX specific attribute so obviously Amazon-S3-FileSystem-NIO2没有提供

其次,Apache MINA SSHD 调用(并需要)S3FileSystemProvider 中的一个未实现的方法,它得到一个 FileChannel

public FileChannel newFileChannel(Path path,
                                  Set<? extends OpenOption> options,
                                  FileAttribute<?>... attrs)

一个 hacky 解决方案只是将 POSIX read/write 权限硬编码到返回的 S3 属性中,并创建一个 S3FileChannel 来简单地调用现有 S3SeekableByteChannel 上的方法.
这是我目前能想到的最好的解决方案。

我们分叉 Amazon-S3-FileSystem-NIO2 并实现了缺失的东西,以便 S3 文件系统与 Apache Mina SFTP 一起工作。

您可以找到 repo here 并使用 maven 在本地构建它。

我们在MINA中的使用方式是这样的:

public FileSystemFactory createFileSystemFactory(String bucketName) throws IOException, URISyntaxException {
    FileSystem fileSystem = FileSystems.newFileSystem(new URI("s3:///"), env, Thread.currentThread().getContextClassLoader());
    String bucketPath = fileSystem.getPath("/" + bucketName);

    return new VirtualFileSystemFactory(bucketPath);
}