4

I just found VFS as a way to access sftp. Seems to work but all the examples assume a local file; instead I have my data in memory. I only see a method copyFrom(FileObject), no overloads accepting a stream or a buffer... So I tried ram as it sounds approximately right (some documentation wouldn't hurt but I can't fine any) and the following test succeeds. Copying into an sftp FileObject also worked.

QUESTION. It gives the following output: INFO: Using "C:\Users\myname\AppData\Local\Temp\vfs_cache" as temporary files store.

-- is it actually writing a temp file?? That's what I was trying to avoid (due to potential permissions/concurrency problems on the Unix servers where this thing will run). If it does, how do I do it completely in-memory?

// try to copy a string from memory into a FileObject
public class VFSTest {

    public static void main(String[] args) throws IOException {
        String hello = "Hello, World!";
        FileObject ram = VFS.getManager().resolveFile("ram:/tmp");
        OutputStream os = ram.getContent().getOutputStream();
        os.write(hello.getBytes());
        ram.getContent().close();

        FileObject local = VFS.getManager().resolveFile("C:\\foo.txt");
        local.copyFrom(ram, Selectors.SELECT_SELF);
    }
}
eckes
  • 10,103
  • 1
  • 59
  • 71
B W
  • 41
  • 1
  • 3
  • If you don't use the ram files for anything than source, it might be better to write your strings or buffers directly to the target (with `write()`). If you create the ram files you could try to directly create the remote files instead and save the ram copy. – eckes Jan 05 '15 at 21:39

2 Answers2

2

This is an old question, but I was having the same problem and I was able to solve it without assuming a local file, so this may be useful for someone having the same problem as B W. Basically, we can copy an input stream directly into the output stream of the remote file.

The code is this:

InputStream is = ... // you only need an input stream, no local file
    
DefaultFileSystemManager fsmanager = (DefaultFileSystemManager) VFS.getManager();
        
FileSystemOptions opts = new FileSystemOptions();
FtpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
StaticUserAuthenticator auth = new StaticUserAuthenticator(host, username, password);
         
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
        
String ftpurl = "ftp://" + host + ":" + port + "/" + folder + "/" + filename;
FileObject remoteFile = fsmanager.resolveFile(ftpurl, opts);
        
try (OutputStream ostream = remoteFile.getContent().getOutputStream()) {
    // either copy input stream manually or with IOUtils.copy()
    IOUtils.copy(is, ostream);
}
        
boolean success = remoteFile.exists();
long size = remoteFile.getContent().getSize();
System.out.println(success ? "Successful, copied " + size + " bytes" : "Failed");
Edu
  • 160
  • 10
1

No, the log message is a general one generated while setting up the file system manager. It is used for the so-called replicator. You do not use it in your example.

Yes ram filesystem is one option to have files in memory. If you on the other hand have an existing data source or byte buffer, you would need to pump it: there is IMHO no function in VFS to read from a InputStream (there is one to write the content of a FileContent to a OutputStream). You typically would use commons-io IOUtils#copy() to do that.

Yes the description is a bit short, but there is really not much to it. The only actual configuration is a possible maximum size. (I actually noticed the file system reference also talks about a predicate for filtering resources, but that is not implemented so I removed it from the 2.1 version of this page).

eckes
  • 10,103
  • 1
  • 59
  • 71