In this tutorial, you will learn how to develop a Java Swing application that allows users uploading a file from his computer to a HTTP server. The application would look like this:

Swing File Upload application

The following diagram explains workflow of the application:

swing file upload application workflow

As we can see, the client is a Swing application that initiates an HTTP POST request to the server. The request must be multipart in order to carry the file to be uploaded. The server side can be implemented in any language as long as it supports parsing HTTP’s multipart request.

For this tutorial, we only discuss how to implement the client side. For the server side, please consult the following tutorials:

The following class diagram gives an idea of how the application would be designed:

swing file upload app class diagram

There are three main classes:

    • MultipartUploadUtility: implements the functionality to upload a file to a server through HTTP’s multipart request. The implementation is based on the tutorial Upload files by sending multipart request programmatically, and is modified to suite requirement of this application: showing progress of the upload.
    • UploadTask: this class extends the javax.swing.SwingWorker class to perform the upload in a background thread so the GUI does not freeze when the progress bar is being updated by the Swing’s event dispatching thread (EDT).
    • SwingFileUploadHTTP: this is the main application which is a JFrame and displays the GUI. It implements the java.beans.PropertyChangeListener interface to be notified about the progress of upload which is sent by the UploadTask class. This class also utilizes the JFilePicker class to show a file chooser component. The JFilePicker in turn, uses the FileTypeFilter class. Refer to the article File picker component in Swing to see how these components are implemented.

Now let’s take closer look at how the main classes are implemented.

 

1. Code of the MultipartUploadUtility class

package net.codejava.swing.upload;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * This utility class provides an abstraction layer for sending multipart HTTP
 * POST requests to a web server.
 * 
 * @author www.codejava.net
 * 
 */
public class MultipartUploadUtility {
	private final String boundary;
	private static final String LINE_FEED = "\r\n";
	private HttpURLConnection httpConn;
	private OutputStream outputStream;
	private PrintWriter writer;

	/**
	 * This constructor initializes a new HTTP POST request with content type is
	 * set to multipart/form-data.
	 * 
	 * @param requestURL
	 * @param charset
	 * @throws IOException
	 */
	public MultipartUploadUtility(String requestURL, String charset)
			throws IOException {

		// creates a unique boundary based on time stamp
		boundary = "===" + System.currentTimeMillis() + "===";

		URL url = new URL(requestURL);
		httpConn = (HttpURLConnection) url.openConnection();
		httpConn.setDoOutput(true); // indicates POST method
		httpConn.setDoInput(true);
		httpConn.setRequestProperty("Content-Type",
				"multipart/form-data; boundary=" + boundary);
		outputStream = httpConn.getOutputStream();
		writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
				true);
	}

	/**
	 * Add a upload file section to the request
	 * 
	 * @param fieldName
	 *            name attribute in <input type="file" name="..." />
	 * @param uploadFile
	 *            a File to be uploaded
	 * @throws IOException
	 */
	public void addFilePart(String fieldName, File uploadFile)
			throws IOException {
		String fileName = uploadFile.getName();
		writer.append("--" + boundary).append(LINE_FEED);
		writer.append(
				"Content-Disposition: form-data; name=\"" + fieldName
						+ "\"; filename=\"" + fileName + "\"")
				.append(LINE_FEED);
		writer.append(
				"Content-Type: "
						+ URLConnection.guessContentTypeFromName(fileName))
				.append(LINE_FEED);
		writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
		writer.append(LINE_FEED);
		writer.flush();
	}

	/**
	 * Write an array of bytes to the request's output stream.
	 */
	public void writeFileBytes(byte[] bytes, int offset, int length)
			throws IOException {
		outputStream.write(bytes, offset, length);
	}

	/**
	 * Complete the request and receives response from the server.
	 * 
	 * @throws IOException
	 *             if any network error occurred or the server returns
	 *             non-HTTP_OK status code.
	 */
	public void finish() throws IOException {
		outputStream.flush();
		writer.append(LINE_FEED);
		writer.flush();

		writer.append(LINE_FEED).flush();
		writer.append("--" + boundary + "--").append(LINE_FEED);
		writer.close();

		// check server's status code first
		int status = httpConn.getResponseCode();
		if (status == HttpURLConnection.HTTP_OK) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					httpConn.getInputStream()));
			while (reader.readLine() != null) {
				// do nothing, but necessary to consume response from the server
			}
			reader.close();
			httpConn.disconnect();
		} else {
			throw new IOException("Server returned non-OK status: " + status);
		}
	}
}

 

2. Code of the UploadTask class

package net.codejava.swing.upload;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

/**
 * Executes the file upload in a background thread and updates progress to 
 * listeners that implement the java.beans.PropertyChangeListener interface.
 * @author www.codejava.net
 *
 */
public class UploadTask extends SwingWorker<Void, Integer> {
	private String uploadURL;
	private File uploadFile;

	public UploadTask(String uploadURL, File uploadFile) {
		this.uploadURL = uploadURL;
		this.uploadFile = uploadFile;
	}

	/**
	 * Executed in background thread
	 */
	@Override
	protected Void doInBackground() throws Exception {
		try {
			MultipartUploadUtility util = new MultipartUploadUtility(uploadURL,
					"UTF-8");
			util.addFilePart("uploadFile", uploadFile);

			FileInputStream inputStream = new FileInputStream(uploadFile);
			byte[] buffer = new byte[4096];
			int bytesRead = -1;
			long totalBytesRead = 0;
			int percentCompleted = 0;
			long fileSize = uploadFile.length();

			while ((bytesRead = inputStream.read(buffer)) != -1) {
				util.writeFileBytes(buffer, 0, bytesRead);
				totalBytesRead += bytesRead;
				percentCompleted = (int) (totalBytesRead * 100 / fileSize);
				setProgress(percentCompleted);
			}

			inputStream.close();
			util.finish();
		} catch (IOException ex) {
			JOptionPane.showMessageDialog(null, "Error uploading file: " + ex.getMessage(),
					"Error", JOptionPane.ERROR_MESSAGE);			
			ex.printStackTrace();
			setProgress(0);
			cancel(true);
		}

		return null;
	}

	/**
	 * Executed in Swing's event dispatching thread
	 */
	@Override
	protected void done() {
		if (!isCancelled()) {
			JOptionPane.showMessageDialog(null,
					"File has been uploaded successfully!", "Message",
					JOptionPane.INFORMATION_MESSAGE);
		}
	}
}

 

3. Code of the SwingFileUploadHTTP class

package net.codejava.swing.upload;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import net.codejava.swing.JFilePicker;

/**
 * A Swing application that uploads files to a HTTP server.
 * @author www.codejava.net
 *
 */
public class SwingFileUploadHTTP extends JFrame implements
		PropertyChangeListener {
	private JLabel labelURL = new JLabel("Upload URL: ");
	private JTextField fieldURL = new JTextField(30);

	private JFilePicker filePicker = new JFilePicker("Choose a file: ",
			"Browse");

	private JButton buttonUpload = new JButton("Upload");

	private JLabel labelProgress = new JLabel("Progress:");
	private JProgressBar progressBar = new JProgressBar(0, 100);

	public SwingFileUploadHTTP() {
		super("Swing File Upload to HTTP server");

		// set up layout
		setLayout(new GridBagLayout());
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.anchor = GridBagConstraints.WEST;
		constraints.insets = new Insets(5, 5, 5, 5);

		// set up components
		filePicker.setMode(JFilePicker.MODE_OPEN);

		buttonUpload.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				buttonUploadActionPerformed(event);
			}
		});

		progressBar.setPreferredSize(new Dimension(200, 30));
		progressBar.setStringPainted(true);

		// add components to the frame
		constraints.gridx = 0;
		constraints.gridy = 0;
		add(labelURL, constraints);

		constraints.gridx = 1;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.weightx = 1.0;
		add(fieldURL, constraints);

		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.weightx = 0.0;
		constraints.gridwidth = 2;
		constraints.fill = GridBagConstraints.NONE;
		add(filePicker, constraints);

		constraints.gridy = 2;
		constraints.anchor = GridBagConstraints.CENTER;
		add(buttonUpload, constraints);

		constraints.gridx = 0;
		constraints.gridy = 3;
		constraints.gridwidth = 1;
		constraints.anchor = GridBagConstraints.WEST;
		add(labelProgress, constraints);

		constraints.gridx = 1;
		constraints.weightx = 1.0;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		add(progressBar, constraints);

		pack();
		setLocationRelativeTo(null);	// center on screen
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	/**
	 * handle click event of the Upload button
	 */
	private void buttonUploadActionPerformed(ActionEvent event) {
		String uploadURL = fieldURL.getText();
		String filePath = filePicker.getSelectedFilePath();

		// validate input first
		if (uploadURL.equals("")) {
			JOptionPane.showMessageDialog(this, "Please enter upload URL!",
					"Error", JOptionPane.ERROR_MESSAGE);
			fieldURL.requestFocus();
			return;
		}

		if (filePath.equals("")) {
			JOptionPane.showMessageDialog(this,
					"Please choose a file to upload!", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}

		try {
			File uploadFile = new File(filePath);
			progressBar.setValue(0);

			UploadTask task = new UploadTask(uploadURL, uploadFile);
			task.addPropertyChangeListener(this);
			task.execute();
		} catch (Exception ex) {
			JOptionPane.showMessageDialog(this,
					"Error executing upload task: " + ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * Update the progress bar's state whenever the progress of upload changes.
	 */
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if ("progress" == evt.getPropertyName()) {
			int progress = (Integer) evt.getNewValue();
			progressBar.setValue(progress);
		}
	}

	/**
	 * Launch the application
	 */
	public static void main(String[] args) {
		try {
			// set look and feel to system dependent
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				new SwingFileUploadHTTP().setVisible(true);
			}
		});
	}
}

 

4. Testing the application

To test the client program, we will use the file upload servlet application as described in the tutorial File Upload servlet with Apache Common File Upload API. So make sure you have the UploadServletApp application deployed on Tomcat server and notice URL of the servlet that handles file upload is:

http://localhost:8080/UploadServletApp/UploadServlet

Now launch the SwingFileUploadHTTP program. Enter the above URL into the Upload URL field, and click Browse button to pick a file:

test SwingFileUploadHTTP

Click Upload button to start uploading the file, and the progress bar shows progress of upload like this:

Swing File Upload application

A message dialog appears when the upload is done:

upload success message

In case of error, such as the Upload URL is mistyped, an error message appears like this:

upload error message

You can download full source code and executable jar file of this application in the attachments section. There's also GitHub repository available for this project.

NOTE:the application must be compiled and executed with Java 1.6 or later.

 

Related Tutorials:

 

Other Java Coding Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Attachments:
Download this file (SwingFileUploadHTTP.zip)SwingFileUploadHTTP.zip[Full source code and executable jar file]26 kB

Add comment

   


Comments 

#26Josue2019-12-05 23:31
Quoting Nam:
Quoting Josue:
how could I send other parameters in the body, apart from the file, for example: {param1: 1, param2: "text"}

You can use the addFormField() method of the MultipartUtility class here: codejava.net/.../...

thanks, you saved my life
Quote
#25Nam2019-12-05 20:28
Quoting Josue:
how could I send other parameters in the body, apart from the file, for example: {param1: 1, param2: "text"}

You can use the addFormField() method of the MultipartUtility class here: codejava.net/.../...
Quote
#24Josue2019-12-04 22:08
how could I send other parameters in the body, apart from the file, for example: {param1: 1, param2: "text"}
Quote
#23Jose2018-05-27 20:34
Someone Has the Server Code but in PHP, Thanks and Regards ...
Quote
#22Sakthi2016-10-27 01:10
where i use my server url for this code. For example, i want to upload file in www.example.com url then how to use this
Quote