deadfish
deadfish

Reputation: 12304

Sending file from client to server and do not lost connection, is it possible?

I would like to send file from client to server and be able do it again in the future.

So my client connect to server and upload file, ok - it works but it hangs at the end..

so here is my code in client, the server side is quite similar.

private void SenderFile(File file) {


    try {

            FileInputStream fis = new FileInputStream(file);
            OutputStream os = socket.getOutputStream();

            IoUtil.copy(fis, os);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

IoUtils found on Stack :)

public static class IoUtil {

    private final static int bufferSize = 8192;

    public static void copy(InputStream in, OutputStream out)
            throws IOException {
        byte[] buffer = new byte[bufferSize];
        int read;

        while ((read = in.read(buffer, 0, bufferSize)) != -1) {
            out.write(buffer, 0, read);
        }
        out.flush();
    }
}

Explanation: my client has a socket connected to server, and I send any file to him. My server download it but hangs at the end because he is listening for more infromation. If I choose another file, my server will download new data to the existing one.

How could I upload any file to server, make my server work on and be able download another one file properly?

ps. If I add to ioutil.copy at the end of function out.close my server will work on but the connection will be lost. I do not know what to do :{


After update: Client side:

private void SenderFile(File file) {
    try {

        FileInputStream fis = new FileInputStream(file);
        OutputStream os = socket.getOutputStream();

        DataOutputStream wrapper = new DataOutputStream(os);
        wrapper.writeLong(file.length());
        IoUtil.copy(fis, wrapper);

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

Server side (thread listening for any message from client):

public void run() {
    String msg;
    File newfile;

    try {
        //Nothing special code here

        while ((msg = reader.readLine()) != null) {


            String[] message = msg.split("\\|");
            if (message[0].equals("file")) {//file|filename|size

                String filename = message[1];
                //int filesize = Integer.parseInt(message[2]);

                newfile = new File("server" + filename);


                InputStream is = socket.getInputStream();
                OutputStream os = new FileOutputStream(newfile);

                DataInputStream wrapper = new DataInputStream(is);

                long fileSize = wrapper.readLong();
                byte[] fileData = new byte[(int) fileSize];
                is.read(fileData, 0, (int) fileSize);
                os.write(fileData, 0, (int) fileSize);


                System.out.println("Downloaded file");
            } else

                //Nothing special here too
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

Ok, now I can download file - still once, another one is downloaded but unable to read. For example, second time I want send by client a file.png. I got it on server, but this file is not possible to view. Thanks in advance :)

Upvotes: 0

Views: 1872

Answers (1)

zneak
zneak

Reputation: 138031

You need to make your server able to differentiate files. The easiest way is to tell in advance how many bytes the receiving end should expect for a single file; this way, it knows when to stop reading and wait for another one.

This is what the SenderFile method could look like:

private void SenderFile(File file)
{
    try
    {
        FileInputStream fis = new FileInputStream(file);
        OutputStream os = socket.getOutputStream();

        DataOutputStream wrapper = new DataOutputStream(os);
        wrapper.writeLong(file.length());
        IoUtil.copy(fis, wrapper);
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}

And this is what the ReceiveFile method could look like:

// the signature of the method is complete speculation, adapt it to your needs
private void ReceiveFile(File file)
{
    FileOutputStream fos = new File(file);
    InputStream is = socket.getInputStream();
    DataInputStream wrapper = new DataInputStream(is);

    // will not work for very big files, adapt to your needs too
    long fileSize = wrapper.readLong();
    byte[] fileData = new byte[fileSize];
    is.read(fileData, 0, fileSize);
    fos.write(fileData, 0, fileSize);
}

Then don't close the socket.

Upvotes: 2

Related Questions