Java get file size and download using HTTP

4 minute read

Today I wanted to download a file using Http protocol but before that determine its size. First aff all I open an Http connection and get file size using Content-Length header (see getFileSize method). Then I download the binary file. You can download the source code from here.


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A simple utility class which provides methods for file downloading using HTTP
 * protocol.
 */
public class FileDownloader {

	private static final Logger logger = LoggerFactory
			.getLogger(FileDownloader.class);

	/**
	 * Gets file size using an HTTP connection with GET method
	 * 
	 * @return file size in bytes
	 * @throws IOException
	 */
	public static long getFileSize(String fileUrl) throws IOException {

		URL oracle = new URL(fileUrl);

		HttpURLConnection yc = (HttpURLConnection) oracle.openConnection();
		populateDesktopHttpHeaders(yc);

		long fileSize = 0;
		try {
			// retrieve file size from Content-Length header field
			fileSize = Long.parseLong(yc.getHeaderField("Content-Length"));
		} catch (NumberFormatException nfe) {
		}

		return fileSize;
	}

	/**
	 * Downloads a file from a given url and writes it to a file in current
	 * working directory
	 * 
	 * @param urli
	 *            Input file url
	 * 
	 * @throws IOException
	 *             ,MalformedURLException
	 */
	public static void downloadFile(String urli) throws IOException,
			MalformedURLException {
		String fileName = urli.substring(urli.lastIndexOf('/') + 1,
				urli.length());

		// download the file in the current working directory
		File outFile = new File(fileName);

		logger.debug("url file name: {}", fileName);
		logger.debug("Output file path: {}", outFile.getAbsolutePath());

		downloadFile(urli, outFile);
	}

	/**
	 * Downloads a file from a given url and writes it to a given File object
	 * 
	 * @param urli
	 *            Input file url
	 * @param outputFile
	 *            The output file to write to
	 * 
	 */
	public static void downloadFile(String urli, File outputFile)
			throws IOException, MalformedURLException {

		long startTime = System.currentTimeMillis();

		// Get a connection to the URL and start up a buffered reader.
		URL url = new URL(urli);
		url.openConnection();
		InputStream reader = url.openStream();

		// Setup a buffered file writer to write out what we read from the
		// website.
		FileOutputStream writer = new FileOutputStream(outputFile);
		byte[] buffer = new byte[153600];
		long totalBytesRead = 0;
		int bytesRead = 0;

		while ((bytesRead = reader.read(buffer)) > 0) {
			writer.write(buffer, 0, bytesRead);
			// buffer = new byte[153600];
			totalBytesRead += bytesRead;
			// logger.debug("Downloaded {} Kb ", (totalBytesRead / 1024));
		}

		long endTime = System.currentTimeMillis();

		logger.debug("Done. {} bytes read in : {} millseconds",
				String.valueOf(totalBytesRead),
				String.valueOf(endTime - startTime));

		writer.close();
		reader.close();
	}

	/**
	 * Downloads a file from a given url and writes it byte array
	 * 
	 * @param urli
	 *            Input file url
	 * 
	 * 
	 */
	public static byte[] downloadFileToArray(String urli) throws IOException,
			MalformedURLException {

		return downloadFileToArray(urli, 0, 0);
	}

	/**
	 * Downloads a file from a given url and writes it to a byte array
	 * 
	 * @param urli
	 *            Input file URL
	 * @param connectionTimeout
	 *            the maximum time in milliseconds to wait while connecting
	 * @param readTimeout
	 *            the read timeout in milliseconds, or 0 if reads never timeout
	 * 
	 * 
	 */
	public static byte[] downloadFileToArray(String urli,
			int connectionTimeout, int readTimeout) throws IOException,
			MalformedURLException {

		long startTime = System.currentTimeMillis();

		// Get a connection to the URL and start up a buffered reader.
		URL url = new URL(urli);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();

		populateDesktopHttpHeaders(con);

		con.setConnectTimeout(connectionTimeout);
		con.setReadTimeout(readTimeout);

		InputStream reader = con.getInputStream();

		// Setup a buffered file writer to write out what we read from the
		// website.
		ByteArrayOutputStream writer = new ByteArrayOutputStream();
		byte[] buffer = new byte[153600];
		long totalBytesRead = 0;
		int bytesRead = 0;

		while ((bytesRead = reader.read(buffer)) > 0) {
			writer.write(buffer, 0, bytesRead);
			// buffer = new byte[153600];
			totalBytesRead += bytesRead;
			// logger.debug("Downloaded {} Kb ", (totalBytesRead / 1024));
		}

		long endTime = System.currentTimeMillis();

		// write all bytes to buffer
		buffer = writer.toByteArray();

		// logger.debug(
		// "Downloaded {}. {} bytes read in {} ",
		// new Object[] { urli, String.valueOf(totalBytesRead),
		// TimeUtils.getDuration(startTime, endTime) });

		con.disconnect();
		writer.close();
		reader.close();

		return buffer;
	}

	private static void populateDesktopHttpHeaders(URLConnection urlCon) {
		// add custom header in order to be easily detected
		urlCon.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");
		urlCon.setRequestProperty("Accept-Language",
				"el-gr,el;q=0.8,en-us;q=0.5,en;q=0.3");
		urlCon.setRequestProperty("Accept-Charset",
				"ISO-8859-7,utf-8;q=0.7,*;q=0.7");
	}

}

UPDATE: 2013-12-31: Added more methods and timeout options 2013-06-14: Minor fixes

Comments