Java Socket Programming-File transfer through socket in Java

So far we have discussed  the fundamental concepts of networking with Java . We also discussed the  TCP and UDP modes of communication in Java with suitable examples.In previous chapters we were discussing a chat application in java  and file transfer in Java using socket programming . But the file transfer example we discussed was not a standard one.In this chapter we are discussing a more enhanced version of the file transfer through socket in java  example we discussed earlier.(File transfer can be done using UDP too. It is explained already with good example .Please see the post)

File transfer through socket in Java

Our application has a client and a server.  Our aim is to send a file from the client machine to the server machine. In this case, we are sending the file as a java object.(We already discussed the way to transfer java objects through sockets before) . The object contains the file name , destination path , file content ,status of transfer etc. Lets see the FileEvent.java .We  are sending the file  with  details as attributes of object of this class.

FileEvent.java

import java.io.Serializable;

public class FileEvent implements Serializable {

public FileEvent() {
}

private static final long serialVersionUID = 1L;

private String destinationDirectory;
private String sourceDirectory;
private String filename;
private long fileSize;
private byte[] fileData;
private String status;

public String getDestinationDirectory() {
return destinationDirectory;
}

public void setDestinationDirectory(String destinationDirectory) {
this.destinationDirectory = destinationDirectory;
}

public String getSourceDirectory() {
return sourceDirectory;
}

public void setSourceDirectory(String sourceDirectory) {
this.sourceDirectory = sourceDirectory;
}

public String getFilename() {
return filename;
}

public void setFilename(String filename) {
this.filename = filename;
}

public long getFileSize() {
return fileSize;
}

public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public byte[] getFileData() {
return fileData;
}

public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
}

Now lets see the server code.It simply creates a ServerSocket on port 4445 and waiting for incoming socket connections.Once a connection comes , it accepts the connection.And then it is reading the FileEvent object. Destination directory , file etc are creating. Data is writing to the output file too. Then closing and exiting.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
private ServerSocket serverSocket = null;
private Socket socket = null;
private ObjectInputStream inputStream = null;
private FileEvent fileEvent;
private File dstFile = null;
private FileOutputStream fileOutputStream = null;

public Server() {

}

/**
* Accepts socket connection
*/
public void doConnect() {
try {
serverSocket = new ServerSocket(4445);
socket = serverSocket.accept();
inputStream = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* Reading the FileEvent object and copying the file to disk.
*/
public void downloadFile() {
try {
fileEvent = (FileEvent) inputStream.readObject();
if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
System.out.println("Error occurred ..So exiting");
System.exit(0);
}
String outputFile = fileEvent.getDestinationDirectory() + fileEvent.getFilename();
if (!new File(fileEvent.getDestinationDirectory()).exists()) {
new File(fileEvent.getDestinationDirectory()).mkdirs();
}
dstFile = new File(outputFile);
fileOutputStream = new FileOutputStream(dstFile);
fileOutputStream.write(fileEvent.getFileData());
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("Output file : " + outputFile + " is successfully saved ");
Thread.sleep(3000);
System.exit(0);

} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
Server server = new Server();
server.doConnect();
server.downloadFile();
}
}

Now see the client code.It simply requests for a socket connection .After getting connection, it is creating the FileEvent object which contains the file details along with full content as byte stream.Then writing the FileEvent object to socket and exiting itself.

import java.io.*;
import java.net.Socket;

public class Client {
private Socket socket = null;
private ObjectOutputStream outputStream = null;
private boolean isConnected = false;
private String sourceFilePath = "E:/temp/songs/song1.mp3";
private FileEvent fileEvent = null;
private String destinationPath = "C:/tmp/downloads/";

public Client() {

}

/**
* Connect with server code running in local host or in any other host
*/
public void connect() {
while (!isConnected) {
try {
socket = new Socket("localHost", 4445);
outputStream = new ObjectOutputStream(socket.getOutputStream());
isConnected = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* Sending FileEvent object.
*/
public void sendFile() {
fileEvent = new FileEvent();
String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/") + 1, sourceFilePath.length());
String path = sourceFilePath.substring(0, sourceFilePath.lastIndexOf("/") + 1);
fileEvent.setDestinationDirectory(destinationPath);
fileEvent.setFilename(fileName);
fileEvent.setSourceDirectory(sourceFilePath);
File file = new File(sourceFilePath);
if (file.isFile()) {
try {
DataInputStream diStream = new DataInputStream(new FileInputStream(file));
long len = (int) file.length();
byte[] fileBytes = new byte[(int) len];
int read = 0;
int numRead = 0;
while (read < fileBytes.length && (numRead = diStream.read(fileBytes, read, fileBytes.length - read)) >= 0) {
read = read + numRead;
}
fileEvent.setFileSize(len);
fileEvent.setFileData(fileBytes);
fileEvent.setStatus("Success");
} catch (Exception e) {
e.printStackTrace();
fileEvent.setStatus("Error");
}
} else {
System.out.println("path specified is not pointing to a file");
fileEvent.setStatus("Error");
}
//Now writing the FileEvent object to socket
try {
outputStream.writeObject(fileEvent);
System.out.println("Done...Going to exit");
Thread.sleep(3000);
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

}

public static void main(String[] args) {
Client client = new Client();
client.connect();
client.sendFile();
}
}

If connection is between two different computers , then in place of local host ,ip address of machine in which server is running needs to be given .

Output

The source file is E:/temp/songs/song1.mp3 . After running both Client and Server , the song1.mp3 will be there in C:/tmp/downloads/  in the machine where server is running.

Remember, this application cannot be used to transfer file of very huge size (say 300 MB or above). The maximum size of file that can be transferred  depends on the capacity of JVM using.

See also:

Basics of socket programming

Communication using TCP

Communication using UDP

Chat application in Java using socket programming

Transferring Java objects through sockets