Search code examples
javaclient-serverrmirmiio

Can't pass file via RMI


I can't send FileInputStream to RMI server even though I wrap it in SimpleRemoteInputStream from the RMIIO library. This is what I get when I try run a client app:

Client started
SENDING FILE: file.pdf
paź 29, 2013 1:13:24 PM com.healthmarketscience.rmiio.exporter.RemoteStreamExporter getInstance
INFO: Using stream exporter com.healthmarketscience.rmiio.exporter.DefaultRemoteStreamExporter

This is client app:

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import com.healthmarketscience.rmiio.SimpleRemoteInputStream;

import pl.opa.backuper_common.FileServer;

public class TestClient { 
    public static void main(String[] args) {

        System.setSecurityManager(new RMISecurityManager());
        String fileName = "file.pdf";
        System.out.println("Client started");

        try {
            Remote remote = Naming.lookup("FileServer");
            FileServer server = null;
            if(remote instanceof FileServer)
                server = (FileServer) remote;

            System.out.println("SENDING FILE: " + fileName);
            SimpleRemoteInputStream istream = new SimpleRemoteInputStream(new FileInputStream(fileName));
            server.sendFile(istream.export());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Server method implementation:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import com.healthmarketscience.rmiio.RemoteInputStream;
import com.healthmarketscience.rmiio.RemoteInputStreamClient;

import pl.opa.backuper_common.FileServer;

public class FileServerImpl extends UnicastRemoteObject implements FileServer {

    private static final long serialVersionUID = 1L;

    protected FileServerImpl() throws RemoteException {
        super();
    }

    @Override
    public void sendFile(RemoteInputStream data) throws IOException, RemoteException {
        InputStream input = null;
        try {
            input = RemoteInputStreamClient.wrap(data);
            writeToFile(input);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                input.close();
            }
        }
    }

    private void writeToFile(InputStream stream) throws IOException {
        FileOutputStream output = null;

        try {
            File file = File.createTempFile("data", ".dat");
            output = new FileOutputStream(file);
            int chunk = 4096;
            byte [] result = new byte[chunk];

            int readBytes = 0;
            do {
                readBytes = stream.read(result);
                if (readBytes >= 0)
                    output.write(result, 0, readBytes);
            } while(readBytes != -1);

            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            if(output != null)
                output.close();
        }
    }
}

Solution

  • My guess is this code on the server side is wrong:

    if (readBytes == -1)
        output.write(result, 0, readBytes);
    

    That should probably be:

    if (readBytes > 0)
        output.write(result, 0, readBytes);