Java Quiz Player

Blog Post

Servlet: Transfer File to Desktop App

Feb 13, 2015

This article shows a Java Servlet program transfer a binary data file to a Java desktop client application.

An application with a desktop and web components has a data transfer requirement. The data is to be transferred from the web app to the client app. The web app prepares the data as a binary file and parks it at a staging area.

The client app initiates the data transfer. The client connects to the web server and invokes the servlet program. The servlet writes the file bytes to the output stream and the client reads the bytes as an input stream and creates a file.

After the file is completely transferred, the client prints a success status message. Further, the client program processes the file as needed.

The article has the sections describing the following:

NOTE: The example assumes that the transfer file is a small file of 25 MB size. The application is tested in Java SE 7 and Apache Tomcat 6 environment.

1. The Servlet

The servlet program reads the supplied input file as an input stream and writes to the output stream.

Path transferFilePath = Paths.get(transferDir, "transferfile_server");
InputStream in = Files.newInputStream(transferFilePath);

The input stream's bytes are written to the servlet output stream. The output stream is for writing the binary data in the response.

ServletOutputStream out = resp.getOutputStream();
// resp is the HttpServletResponse
int i = 0;
while ((i = in.read()) != -1) { // -1 indicates end of input stream	
    out.write(i);
}

Writing to stream is done. Close both the streams.

1.1. The Code

The following snippet shows the servlet program's code:

public class FileTransferServlet extends HttpServlet {

    private static final String TRANSFER_FILE = 
	    "X:\\File_Transfer_Example\\transferfile_server";

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException, ServletException {
        boolean transferStatusOk = true;
        InputStream in = null;
        ServletOutputStream out = null;
        Path transferFilePath = Paths.get(TRANSFER_FILE);
        try {
            in = Files.newInputStream(transferFilePath);
            out = resp.getOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
                out.write(i);
            }
            out.flush();
        }
        catch (IOException e) {
            transferStatusOk = false;
            e.printStackTrace();
            throw new ServletException(e);
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (out != null) {
                try {
                    out.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } // try

        // File transfer complete
        if (transferStatusOk) {
            // do something to the successfully transferred file
            // show transfer success status in the web app
        }
    } // doPost()
}

2. The Client

The file data transfer is initiated from the client. The client program runs from the command prompt. The client program communicates with the webserver and the servlet using a HttpURLConnection. This connection is used to read from the resource referenced by the servlet's URL.

URL url = new URL(servletUrl);
// servletUrl is the connection URL to the servlet program
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// specify the servlet's service method; default is GET
connection.setRequestMethod("POST");
connection.connect();
// this establishes the actual network connection

The client reads the file bytes which the servlet writes to the output stream. First, get the input stream from the connection object.

InputStream in = connection.getInputStream();

Copy all the input stream bytes to a file.

Path transferFilePath = Paths.get(transferDir, "transferfile_client");
long fileSize = Files.copy(in, transferFilePath,
	StandardCopyOption.REPLACE_EXISTING);

Transfer is complete. Close stream. Process file data.

2.1. The Code

The following snippet shows the client program's code:

public class FileTransferClient {

    private static final String SERVLET_URL =
	    "http://localhost:8080/FileTransferServlet/go";
    private static final String TRANSFER_FILE = 
	    "X:\\File_Transfer_Example\\transferfile_client";

    public static void main (String [] args)
            throws Exception {
        boolean status = true;
        HttpURLConnection connection = null;
        Path transferFilePath = null;
        try {
            connection = getConnection();
        }
        catch (IOException e) {
            String msg = 
                "Error connecting to the web server application. " +
                "Check if net connectivity is there. " + "Try later.";
            System.out.println(msg);
            e.printStackTrace();
            status = false;
        }

        if ((status == true) && (connection != null)) {
            try {		
                transferFilePath = getTransferFile(connection);
            }
            catch (IOException e) {
                String msg =
                    "Error writing server data to the local file";
                System.out.println(msg);
                e.printStackTrace();
                status = false;
            }
        }

        if (connection != null) {
            try {
                int code = connection.getResponseCode();
                String msg = connection.getResponseMessage();
                msg= "Server status code: " + code + " - " + msg ;
                System.out.println(msg);
            }
            catch (IOException e) {
                e.printStackTrace();
                String msg = "Error reading response status";
                System.out.println(msg);
            }
            connection.disconnect();
        }

        if (status == true) {
            // process transfer file 
            // check file size and read the file...
        }
    } // main()

    private static HttpURLConnection getConnection()
            throws IOException {
        URL url = new URL(SERVLET_URL);
        HttpURLConnection connection =
		    (HttpURLConnection) url.openConnection();
        connection.setDoInput(true); // this is default
        connection.setRequestMethod("POST");
        connection.connect(); // establish the actual network connection
        return connection; 
    }

    private static Path getTransferFile(HttpURLConnection  connection)
            throws IOException {
        InputStream in = connection.getInputStream();
        Path transferFilePath = Paths.get(TRANSFER_FILE);
        long fileSize = Files.copy(in, transferFilePath, 
		    StandardCopyOption.REPLACE_EXISTING);
        return transferFilePath;
    }
}

3. The Transfer Process Status

From the start of the client program's invocation of the transfer process to the end, the status of the process is tracked. There are possibilities that something might go wrong on either client or server side. There is also a success status.

The status tracking includes using the exception handling and servlet response codes on the servlet and the client programs.

Here are some process scenarios. The client starts the process:

There is a case when the transfer file is partially transferred. In this example, a partial file is of no use. A solution is that the transfer input file may be transferred again from the beginning.

3.1. The File Transfer is Successful

3.1.1. The Client

The following is the output at the command prompt.

*** Transfer process begin. ***
Connecting to the server
Connected to the server
Writing transfer file from server to local storage
Writing complete. Number of bytes written: 471
Server status code: 200 - OK
*** Closing transfer process  ***

Note the servlet response code 200 indicating the ok status. The HttpURLConnection's getResponseCode() and getResponseMessage() methods retrieve the code and its message description. These status code descriptions are listed in the HttpServletResponse API and in the HttpURLConnection API javadoc.

The main steps of the client program are: getting the connection, getting an input stream and writing to a file. Note that the client program throws one exception for all the APIs used - IOException or its sub-classes.

3.1.2. The Server

The following output can be viewed on the web server console or in the log files.

*** Transfer process begin. ***
Getting input stream
Getting output stream
File transfer complete.
*** Closing transfer process ***

The main steps of the servlet are: get an input stream for the transfer file and write to the servlet output stream. These two operations throw IOException.

The servlet sets an OK status on the response, by default automatically (this need not be specified unless the programmer intends to set a code or the when there are exceptional cases the system/webserver sets appropriate codes). Note that the status is set before the output is written.

3.2. Server (or Network Connection) is Not Available

The client starts the process, and the server (or network connection) is not available.

3.2.1. The Client

The following is the output at the command prompt.

*** Transfer process begin. ***
Connecting to the server
Error connecting to the web server application.
Check if net connectivity is there. Try later.
java.net.ConnectException: Connection refused: connect
...
  at sun.net.www.protocol.http.HttpURLConnection.connect
    (HttpURLConnection.java:849)
  at FileTransferClient.getConnection(FileTransferClient.java:97)
  at FileTransferClient.main(FileTransferClient.java:30)
*** Closing transfer process  ***

From the Java API's javadoc: java.net.ConnectException is a subclass of java.net.SocketException and java.io.IOException. This signals that an error occurred while attempting to connect a socket to a remote address and port. Typically, the connection was refused remotely (e.g., no process is listening on the remote address/port).

3.2.2. The Server

There is no server error possible in this scenario.

3.3. No File on Server

The client starts the process and the servlet runs, but the input transfer file on server is missing.

3.3.1. The Client

The following is the output at the command prompt.

*** Transfer process begin. ***
Connecting to the server
Connected to the server
Error writing server data to the local file
java.io.IOException: Server returned HTTP response code: 500 for URL: 
http://localhost:8080/FileTransferServlet/go
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream
		(HttpURLConnection.java:1625)
  at FileTransferClient.getTransferFile(FileTransferClient.java:111)
  at FileTransferClient.main(FileTransferClient.java:48)
Server status code: 500 - Internal Server Error
*** Closing transfer process  ***

Note the server status code 500.

3.3.2. The Server

The following output can be viewed on the web server console or in the log files.

SEVERE: Servlet.service() for servlet FileTransferServlet threw exception
java.nio.file.NoSuchFileException:
        X:\File_Transfer_Example\transferfile_server
...
  at app.FileTransferServlet.doPost(FileTransferServlet.java:36)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)

Note the exception java.nio.file.NoSuchFileException; this indicates that the input file on server is missing.

3.4. The Servlet is Missing

The client starts the process and the web server is up and connected to, but the transfer servlet is missing (or not deployed).

3.4.1. The Client

The following is the output at the command prompt.

*** Transfer process begin. ***
Connecting to the server
Connected to the server
Error writing server data to the local file
java.io.FileNotFoundException:
    http://localhost:8080/FileTransferServlet/go
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream
		    (HttpURLConnection.java:1623)
        at FileTransferClient.getTransferFile(FileTransferClient.java:107)
        at FileTransferClient.main(FileTransferClient.java:45)
Server status code: 404 - Not Found
*** Closing transfer process ***

The java.io.FileNotFoundException indicates the failure to get the input stream. Note the server status code 404.

3.4.2. The Server

There is no server error in this scenario.

4. Useful Links

5. Download

Download source code here: FileTransferServletExample.zip

Return to top


Comments

Comments are welcome. Please note that comments are moderated.
Email to: info(at)javaquizplayer(dot)com.