Now let’s take closer look at how the main classes are implemented.
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); } } }
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); } } }
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); } }); } }
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:Click Upload button to start uploading the file, and the progress bar shows progress of upload like this:A message dialog appears when the upload is done:In case of error, such as the Upload URL is mistyped, an error message appears like this: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.